diff --git a/ansible/README.test.md b/ansible/README.test.md index 373a8331a9b..544f190ab57 100644 --- a/ansible/README.test.md +++ b/ansible/README.test.md @@ -9,6 +9,13 @@ - Replace {PTF_HOST} in each command line with the host name or IP of the PTF testbed host - Replace {TESTBED_TYPE} in each command line with the type of the testbed being used +### ACL tests +``` +ansible-playbook test_sonic.yml -i inventory --limit {DUT_NAME} --become --tags acltb_configure --extra-vars "run_dir=/tmp testbed_type={TESTBED_TYPE} ptf_host={PTF_HOST}" +ansible-playbook test_sonic.yml -i inventory --limit {DUT_NAME} --become --tags acltb_test --extra-vars "run_dir=/tmp testbed_type={TESTBED_TYPE} ptf_host={PTF_HOST}" +ansible-playbook test_sonic.yml -i inventory --limit {DUT_NAME} --become --tags acltb_cleanup --extra-vars "run_dir=/tmp testbed_type={TESTBED_TYPE} ptf_host={PTF_HOST}" +``` +- Requires switch connected to a PTF testbed ### ARP tests ``` diff --git a/ansible/action_plugins/switch.py b/ansible/action_plugins/switch.py deleted file mode 100644 index b957a15e2c4..00000000000 --- a/ansible/action_plugins/switch.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.action import ActionBase -from ansible.utils.boolean import boolean -from ansible.utils.unicode import to_unicode - -class ActionModule(ActionBase): - - def run(self, tmp=None, task_vars=None): - if task_vars is None: - task_vars = dict() - - self._display.vvv('ActionModule run') - - result = super(ActionModule, self).run(tmp, task_vars) - - _template = self._task.args.get('template', None) - _host = self._task.args.get('host', None) - _login = self._task.args.get('login', None) - _enable = boolean(self._task.args.get('enable', 'yes')) - _bash = boolean(self._task.args.get('bash', 'no')) - _su = boolean(self._task.args.get('su', 'no')) - _root = boolean(self._task.args.get('root', 'no')) - _reboot = boolean(self._task.args.get('reboot', 'no')) - _timeout = self._task.args.get('timeout', None) - - login = { 'user': [], 'enable': _login['enable'] } - for passwd in reversed(_login['passwd']): - login['user'].append((_login['user'], passwd)) - - if _timeout is None: - _timeout = 30 - - if _template is not None: - if self._task._role is not None: - _template = self._loader.path_dwim_relative(self._task._role._role_path, 'templates', _template) - else: - _template = self._loader.path_dwim_relative(self._loader.get_basedir(), 'templates', _template) - - f = open(_template, 'r') - template_data = to_unicode(f.read()) - f.close() - - _template = self._templar.template(template_data) - - self._display.vvv(self._connection.transport) - result['stdout'] = self._connection.exec_command(template=_template, - host=_host, - login=login, - enable=_enable, - bash=_bash, - su=_su, - root=_root, - reboot=_reboot, - timeout=_timeout) - - return result diff --git a/ansible/basic_check.yml b/ansible/basic_check.yml new file mode 100644 index 00000000000..0f8f1219ee9 --- /dev/null +++ b/ansible/basic_check.yml @@ -0,0 +1,30 @@ + +- hosts: sonic + gather_facts: no + tasks: + + - name: Get process information in syncd docker + shell: docker exec -i syncd ps aux | grep /usr/bin/syncd + register: ps_out + + - debug: var=ps_out.stdout_lines + + - name: Verify that syncd process is running + assert: { that: "{{ ps_out.stdout_lines | length }} > 0"} + + - name: Get syslog error information + shell: cat /var/log/syslog |tail -n 5000 |grep error + become: true + register: syslog_out + failed_when: false + + - debug: var=syslog_out.stdout_lines + + - name: Gathering minigraph facts about the device + minigraph_facts: host={{ inventory_hostname }} + connection: local + become: no + tags: always + + - include: roles/test/tasks/interface.yml + diff --git a/ansible/connection_plugins/switch.py b/ansible/connection_plugins/switch.py deleted file mode 100644 index 47e25db26ac..00000000000 --- a/ansible/connection_plugins/switch.py +++ /dev/null @@ -1,247 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import subprocess -import shlex -import pipes -import pexpect -import random -import select -import fcntl -import pwd -import time - -from ansible import constants as C -from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound -from ansible.plugins.connection import ConnectionBase - -class Connection(ConnectionBase): - ''' ssh based connections with expect ''' - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) - - self.host = self._play_context.remote_addr - self.connection_retry_interval = 60 - - @property - def transport(self): - ''' used to identify this connection object from other classes ''' - return 'cisco' - - # The connection is created by running expect from the exec_command, so we don't - # need to do any connection management here. - - def _connect(self): - self._connect = True - return self - - def _build_command(self): - self._ssh_command = ['ssh', '-tt', '-q'] - ansible_ssh_args = C.ANSIBLE_SSH_ARGS - if ansible_ssh_args: - self._ssh_command += shlex.split(ansible_ssh_args) - else: - self._ssh_command += ['-o', 'ControlMaster=auto', - '-o', 'ControlPersist=60s', - '-o', 'ControlPath=/tmp/ansible-ssh-%h-%p-%r'] - - if not C.HOST_KEY_CHECKING: - self._ssh_command += ['-o', 'StrictHostKeyChecking=no'] - self._ssh_command += ['-o', 'UserKnownHostsFile=/dev/null'] - - self._ssh_command += ['-o', 'GSSAPIAuthentication=no', - '-o', 'PubkeyAuthentication=no'] - self._ssh_command += ['-o', 'ConnectTimeout=30'] - - def _spawn_connect(self): - last_user = None - client = None - attempt = 0 - - self._display.vvv("%s" % self.login) - - while attempt < len(self.login['user']): - (user, login_passwd) = self.login['user'][attempt] - if user != last_user: - if client: - client.close() - cmd = self._ssh_command + ['-l', user, self.host] - self._display.vvv("SSH: EXEC {0}".format(' '.join(cmd)), - host=self.host) - last_user = user - client = pexpect.spawn(' '.join(cmd), env={'TERM': 'dumb'}) - i = client.expect(['[Pp]assword:', pexpect.EOF]) - if i == 1: - self._display.vvv("Server closed the connection, retry in %d seconds" % self.connection_retry_interval, host=self.host) - time.sleep(self.connection_retry_interval) - last_user = None - continue - - self._display.vvv("Try password %s..." % login_passwd[0:4], host=self.host) - client.sendline(login_passwd) - i = client.expect(['>', '#', '[Pp]assword:', pexpect.EOF]) - if i < 2: - break - elif i == 3: - last_user = None - - # try a new password - attempt += 1 - - if attempt == len(self.login['user']): - raise AnsibleError("none of the passwords in the book works") - - self.before_backup = client.before.split() - - # determine the sku - client.sendline('show version') - client.expect(['#', '>']) - if 'Arista' in client.before: - self.sku = 'eos' - elif 'Cisco' in client.before: - self.sku = 'nxos' - if 'MLNX-OS' in client.before: - self.sku = 'mlnx_os' - - if self.sku == 'mlnx_os': - self.hname = ' '.join(self.before_backup[-3:]) - self.hname = self.hname.replace("(", "[(]") - self.hname = self.hname.replace(")", "[)]") - self.hname = self.hname.replace("]", "\]") - self.hname = self.hname.replace("[", "\[") - else: - self.hname = self.before_backup[-1] - self.hname = self.hname.replace("(", "[(]") - self.hname = self.hname.replace(")", "[)]") - - if i == 0 and self.enable: - attempt = 0 - client.sendline('enable') - self.login['enable'].reverse() - while True: - i = client.expect(['#', '[Pp]assword:', '>']) - if i == 1: - if attempt < len(self.login['enable']): - passwd = self.login['enable'][attempt] - client.sendline(passwd) - self._display.vvv("Try enable password %s..." % passwd[0:4], host=self.host) - attempt += 1 - else: - raise AnsibleError("none of the enable passwords works") - elif i == 2: - client.sendline('enable') - else: - break - - if self.bash: - if not self.enable: - raise AnsibleError("can only get into bash with enable") - - if self.sku == "nxos": - self._display.vvv("Enable configure mode", host=self.host) - client.sendline('conf t') - client.expect(['\(config\)#']) - self._display.vvv("Enable bash feature", host=self.host) - client.sendline('feature bash') - client.expect(['\(config\)#']) - client.sendline('run bash') - self._display.vvv("Run bash", host=self.host) - client.expect(['bash-\d.\d\$']) - if self.su: - if user != 'admin': - raise AnsibleError("can only get into bash using local admin account") - client.sendline('sudo su root') - i = client.expect(['Password:', 'bash-\d.\d#']) - if i == 0: - self._display.vvv("Provide sudo password", host=self.host) - client.sendline(login_passwd) - client.expect(['bash-\d.\d#']) - self._display.vvv("Entered bash with root", host=self.host) - else: - self._display.vvv("Entered bash", host=self.host) - elif self.sku == "eos": - client.sendline('bash') - client.expect(['\$ ']) - else: - raise AnsibleError("do not support shell mode for sku %s" % self.sku) - - return client - - def exec_command(self, *args, **kwargs): - - self.template = kwargs['template'] - if kwargs['host'] is not None: - self.host = kwargs['host'] - self.login = kwargs['login'] - self.enable = kwargs['enable'] - self.bash = kwargs['bash'] - self.su = kwargs['su'] - self.reboot = kwargs['reboot'] - if kwargs['root']: - self.login['user'] = 'root' - self._build_command() - - client = self._spawn_connect() - - # Set command timeout after connection is spawned - if kwargs['timeout']: - client.timeout = int(kwargs['timeout']) - - # "%s>": non privileged prompt - # "%s(\([a-z\-]+\))?#": privileged prompt including configure mode - # Prompt includes Login, Password, and yes/no for "start shell" case in Dell FTOS (launch bash shell) - if not self.bash: - prompts = ["%s>" % self.hname, "%s.+" % self.hname, "%s(\([a-zA-Z0-9\/\-]+\))?#" % self.hname, '[Ll]ogin:', '[Pp]assword:', '\[(confirm )?yes\/no\]:', '\(y\/n\)\??\s?\[n\]'] - else: - if self.sku == 'nxos': - # bash-3.2$ for nexus 6.5 - prompts = ['bash-3\.2\$', 'bash-3\.2#'] - elif self.sku == 'eos': - prompts = ['\$ '] - - prompts.append(pexpect.EOF) - - stdout = "" - if self.template: - cmds = self.template.split('\n') - else: - cmds = [] - for cmd in cmds: - self._display.vvv('> %s' % (cmd), host=self.host) - client.sendline(cmd) - client.expect(prompts) - stdout += client.before - self._display.vvv('< %s' % (client.before), host=self.host) - - if self.reboot: - if not self.enable: - raise AnsibleError("can only reboot the box in enable mode") - client.sendline('reload') - # Proceed with reload\? \[confirm\] : EOS - i = client.expect(['\(y\/n\)\??\s*\[n\]', 'Proceed with reload\? \[confirm\]', 'System configuration has been modified. Save\? \[yes\/no\/cancel\/diff\]:']) - if i == 2: - # EOS behavior - stdout += client.before - client.sendline('n') - i = client.expect('Proceed with reload\? \[confirm\]') - stdout += client.before - client.sendline('y') - # The system is going down for reboot NOW: EOS - i = client.expect(['>', '#', 'The system is going down for reboot NOW', pexpect.TIMEOUT, pexpect.EOF]) - stdout += client.before - if i < 2: - raise AnsibleError("Box failed to reboot. stdout = %s" % stdout) - self._display.vvv("Box rebooted", host=self.host) - - return stdout - - def put_file(self, in_path, out_path): - pass - - def fetch_file(self, in_path, out_path): - pass - - def close(self): - self._connected = False diff --git a/ansible/files/creategraph.py b/ansible/files/creategraph.py index db33e8525e3..0526647c8f5 100644 --- a/ansible/files/creategraph.py +++ b/ansible/files/creategraph.py @@ -2,15 +2,15 @@ import csv, sys, os from lxml import etree -DEVICECSV = 'sonic_str_devices.csv' -LINKCSV = 'sonic_str_links.csv' -STARLAB_CONNECTION_GRAPH_ROOT_NAME = 'StarlabConnectionGraph' -STARLAB_CONNECTION_GRAPH_DPGL2_NAME = 'DevicesL2Info' +DEVICECSV = 'sonic_lab_devices.csv' +LINKCSV = 'sonic_lab_links.csv' +LAB_CONNECTION_GRAPH_ROOT_NAME = 'LabConnectionGraph' +LAB_CONNECTION_GRAPH_DPGL2_NAME = 'DevicesL2Info' class LabGraph(object): """ - This is used to create "graph" file of starlab for all connections and vlan info from csv file + This is used to create "graph" file of lab for all connections and vlan info from csv file We(both engineer and lab technician) maintian and modify the csv file to keep track of the lab infrastucture for Sonic development and testing environment. """ @@ -63,7 +63,7 @@ def generate_dpg(self): l3inforoot = etree.SubElement(self.dpgroot, 'DevicesL3Info', {'Hostname': hostname}) etree.SubElement(l3inforoot, 'ManagementIPInterface', {'Name': 'ManagementIp', 'Prefix': managementip}) ####### Build L2 information Here - l2inforoot = etree.SubElement(self.dpgroot, STARLAB_CONNECTION_GRAPH_DPGL2_NAME, {'Hostname': hostname}) + l2inforoot = etree.SubElement(self.dpgroot, LAB_CONNECTION_GRAPH_DPGL2_NAME, {'Hostname': hostname}) vlanattr = {} for link in self.links: if link['StartDevice'] == hostname: @@ -90,7 +90,7 @@ def create_xml(self): ''' onexml = open(self.one_xmlfile, 'w') - root=etree.Element(STARLAB_CONNECTION_GRAPH_ROOT_NAME) + root=etree.Element(LAB_CONNECTION_GRAPH_ROOT_NAME) root.append(self.pngroot) root.append(self.dpgroot) result = etree.tostring(root, pretty_print=True) diff --git a/ansible/files/starlab_connection_graph.xml b/ansible/files/lab_connection_graph.xml similarity index 99% rename from ansible/files/starlab_connection_graph.xml rename to ansible/files/lab_connection_graph.xml index 94af87054ad..7d04498322f 100644 --- a/ansible/files/starlab_connection_graph.xml +++ b/ansible/files/lab_connection_graph.xml @@ -1,4 +1,4 @@ - + diff --git a/ansible/files/sonic_str_devices.csv b/ansible/files/sonic_lab_devices.csv similarity index 100% rename from ansible/files/sonic_str_devices.csv rename to ansible/files/sonic_lab_devices.csv diff --git a/ansible/files/sonic_str_links.csv b/ansible/files/sonic_lab_links.csv similarity index 100% rename from ansible/files/sonic_str_links.csv rename to ansible/files/sonic_lab_links.csv diff --git a/ansible/files/sonic_server_links.yml b/ansible/files/sonic_server_links.yml deleted file mode 100644 index c94c8d6eeab..00000000000 --- a/ansible/files/sonic_server_links.yml +++ /dev/null @@ -1,3 +0,0 @@ -str-acs-serv-01: - str-msn2700-01: ptf1-m - diff --git a/ansible/group_vars/lab/lab.yml b/ansible/group_vars/lab/lab.yml new file mode 100644 index 00000000000..2cafa9d4b04 --- /dev/null +++ b/ansible/group_vars/lab/lab.yml @@ -0,0 +1,16 @@ +--- +#starlab (str) group variables +# file: group_vars/str.yml + +# ntp variables +ntp_servers: ['10.0.0.1', '10.0.0.2'] + +# syslog variables +syslog_servers: ['10.0.0.5', '10.0.0.6'] +# +# dns variables +dns_servers: ['10.0.0.5', '10.0.0.6'] +# +# snmp variables +snmp_rocommunity: public +snmp_location: testlab diff --git a/ansible/group_vars/str/strinfo.json b/ansible/group_vars/lab/labinfo.json similarity index 100% rename from ansible/group_vars/str/strinfo.json rename to ansible/group_vars/lab/labinfo.json diff --git a/ansible/group_vars/lab/secrets.yml b/ansible/group_vars/lab/secrets.yml new file mode 100644 index 00000000000..c0d5afdb972 --- /dev/null +++ b/ansible/group_vars/lab/secrets.yml @@ -0,0 +1,5 @@ +ansible_ssh_pass: password +ansible_become_pass: password +sonicadmin_user: admin +sonicadmin_password: password +sonicadmin_initial_password: password diff --git a/ansible/group_vars/sonic/sku-sensors-data.yml b/ansible/group_vars/sonic/sku-sensors-data.yml new file mode 100644 index 00000000000..53fc237d792 --- /dev/null +++ b/ansible/group_vars/sonic/sku-sensors-data.yml @@ -0,0 +1,405 @@ +sensors_checks: + Force10-S6000: + alarms: + fan: + - dni_dps460-i2c-1-58/fan1/fan1_alarm + - dni_dps460-i2c-1-58/fan1/fan1_fault + - dni_dps460-i2c-1-59/fan1/fan1_alarm + - dni_dps460-i2c-1-59/fan1/fan1_fault + power: + - w83627dhg-isa-0a00/VCore 1/in0_alarm + - w83627dhg-isa-0a00/VCore 2/in1_alarm + - w83627dhg-isa-0a00/AVCC/in2_alarm + - w83627dhg-isa-0a00/+3.3V/in3_alarm + - w83627dhg-isa-0a00/3VSB/in7_alarm + - w83627dhg-isa-0a00/Vbat/in8_alarm + - ltc4215-i2c-11-40/in1/in1_min_alarm + - ltc4215-i2c-11-40/in1/in1_max_alarm + - ltc4215-i2c-11-40/in2/in2_min_alarm + - ltc4215-i2c-11-40/curr1/curr1_max_alarm + - ltc4215-i2c-11-42/in1/in1_min_alarm + - ltc4215-i2c-11-42/in1/in1_max_alarm + - ltc4215-i2c-11-42/in2/in2_min_alarm + - ltc4215-i2c-11-42/curr1/curr1_max_alarm + temp: + - coretemp-isa-0000/Core 0/temp2_crit_alarm + - coretemp-isa-0000/Core 1/temp3_crit_alarm + - jc42-i2c-10-18/temp1/temp1_max_alarm + - jc42-i2c-10-18/temp1/temp1_min_alarm + - jc42-i2c-10-18/temp1/temp1_crit_alarm + - emc1403-i2c-10-4d/temp1/temp1_max_alarm + - emc1403-i2c-10-4d/temp1/temp1_min_alarm + - emc1403-i2c-10-4d/temp1/temp1_crit_alarm + - emc1403-i2c-10-4d/temp2/temp2_max_alarm + - emc1403-i2c-10-4d/temp2/temp2_min_alarm + - emc1403-i2c-10-4d/temp2/temp2_crit_alarm + - emc1403-i2c-10-4d/temp2/temp2_fault + - emc1403-i2c-10-4d/temp3/temp3_max_alarm + - emc1403-i2c-10-4d/temp3/temp3_min_alarm + - emc1403-i2c-10-4d/temp3/temp3_crit_alarm + - emc1403-i2c-10-4d/temp3/temp3_fault + - dni_dps460-i2c-1-58/temp1/temp1_max_alarm + - dni_dps460-i2c-1-58/temp2/temp2_max_alarm + - dni_dps460-i2c-1-59/temp1/temp1_max_alarm + - dni_dps460-i2c-1-59/temp2/temp2_max_alarm + compares: + fan: [] + power: [] + temp: + - - acpitz-virtual-0/temp1/temp1_input + - acpitz-virtual-0/temp1/temp1_crit + - - acpitz-virtual-0/temp2/temp2_input + - acpitz-virtual-0/temp2/temp2_crit + - - tmp75-i2c-11-4c/temp1/temp1_input + - tmp75-i2c-11-4c/temp1/temp1_max + - - tmp75-i2c-11-4d/temp1/temp1_input + - tmp75-i2c-11-4d/temp1/temp1_max + - - tmp75-i2c-11-4e/temp1/temp1_input + - tmp75-i2c-11-4e/temp1/temp1_max + non_zero: + fan: + - max6620-i2c-11-29/fan1/fan1_input + - max6620-i2c-11-29/fan2/fan2_input + - max6620-i2c-11-29/fan3/fan3_input + - max6620-i2c-11-29/fan4/fan4_input + - max6620-i2c-11-2a/fan1/fan1_input + - max6620-i2c-11-2a/fan2/fan2_input + power: [] + temp: [] + psu_skips: + dni_dps460-i2c-1-58: + number: 2 + side: right + skip_list: + - dni_dps460-i2c-1-58 + - ltc4215-i2c-11-40 + dni_dps460-i2c-1-59: + number: 1 + side: left + skip_list: + - dni_dps460-i2c-1-59 + - ltc4215-i2c-11-42 + + ACS-MSN2700: + alarms: + fan: + - dps460-i2c-10-59/fan1/fan1_alarm + - dps460-i2c-10-58/fan1/fan1_alarm + power: + - dps460-i2c-10-59/vin/in1_min_alarm + - dps460-i2c-10-59/vin/in1_max_alarm + - dps460-i2c-10-59/vin/in1_lcrit_alarm + - dps460-i2c-10-59/vin/in1_crit_alarm + - dps460-i2c-10-59/vout1/in3_min_alarm + - dps460-i2c-10-59/vout1/in3_max_alarm + - dps460-i2c-10-59/vout1/in3_lcrit_alarm + - dps460-i2c-10-59/vout1/in3_crit_alarm + - dps460-i2c-10-59/pin/power1_alarm + - dps460-i2c-10-59/pout1/power2_cap_alarm + - dps460-i2c-10-59/pout1/power2_max_alarm + - dps460-i2c-10-59/pout1/power2_crit_alarm + - dps460-i2c-10-59/iin/curr1_max_alarm + - dps460-i2c-10-59/iin/curr1_crit_alarm + - dps460-i2c-10-59/iout1/curr2_max_alarm + - dps460-i2c-10-59/iout1/curr2_lcrit_alarm + - dps460-i2c-10-59/iout1/curr2_crit_alarm + - dps460-i2c-10-58/vin/in1_min_alarm + - dps460-i2c-10-58/vin/in1_max_alarm + - dps460-i2c-10-58/vin/in1_lcrit_alarm + - dps460-i2c-10-58/vin/in1_crit_alarm + - dps460-i2c-10-58/vout1/in3_min_alarm + - dps460-i2c-10-58/vout1/in3_max_alarm + - dps460-i2c-10-58/vout1/in3_lcrit_alarm + - dps460-i2c-10-58/vout1/in3_crit_alarm + - dps460-i2c-10-58/pin/power1_alarm + - dps460-i2c-10-58/pout1/power2_cap_alarm + - dps460-i2c-10-58/pout1/power2_max_alarm + - dps460-i2c-10-58/pout1/power2_crit_alarm + - dps460-i2c-10-58/iin/curr1_max_alarm + - dps460-i2c-10-58/iin/curr1_crit_alarm + - dps460-i2c-10-58/iout1/curr2_max_alarm + - dps460-i2c-10-58/iout1/curr2_lcrit_alarm + - dps460-i2c-10-58/iout1/curr2_crit_alarm + - ucd9200-i2c-5-27/UCD1 vin/in1_min_alarm + - ucd9200-i2c-5-27/UCD1 vin/in1_max_alarm + - ucd9200-i2c-5-27/UCD1 vin/in1_lcrit_alarm + - ucd9200-i2c-5-27/UCD1 vin/in1_crit_alarm + - ucd9200-i2c-5-27/ASIC 3.3 vout/in2_min_alarm + - ucd9200-i2c-5-27/ASIC 3.3 vout/in2_max_alarm + - ucd9200-i2c-5-27/ASIC 3.3 vout/in2_lcrit_alarm + - ucd9200-i2c-5-27/ASIC 3.3 vout/in2_crit_alarm + - ucd9200-i2c-5-27/ASIC 1.2 vout/in3_min_alarm + - ucd9200-i2c-5-27/ASIC 1.2 vout/in3_max_alarm + - ucd9200-i2c-5-27/ASIC 1.2 vout/in3_lcrit_alarm + - ucd9200-i2c-5-27/ASIC 1.2 vout/in3_crit_alarm + - ucd9200-i2c-5-27/iout1/curr2_max_alarm + - ucd9200-i2c-5-27/iout1/curr2_lcrit_alarm + - ucd9200-i2c-5-27/iout1/curr2_crit_alarm + - ucd9200-i2c-5-27/iout2/curr3_max_alarm + - ucd9200-i2c-5-27/iout2/curr3_lcrit_alarm + - ucd9200-i2c-5-27/iout2/curr3_crit_alarm + - ucd9200-i2c-5-41/UCD2 vin/in1_min_alarm + - ucd9200-i2c-5-41/UCD2 vin/in1_max_alarm + - ucd9200-i2c-5-41/UCD2 vin/in1_lcrit_alarm + - ucd9200-i2c-5-41/UCD2 vin/in1_crit_alarm + - ucd9200-i2c-5-41/ASIC Vcore vout/in2_min_alarm + - ucd9200-i2c-5-41/ASIC Vcore vout/in2_max_alarm + - ucd9200-i2c-5-41/ASIC Vcore vout/in2_lcrit_alarm + - ucd9200-i2c-5-41/ASIC Vcore vout/in2_crit_alarm + - ucd9200-i2c-5-41/iout1/curr2_max_alarm + - ucd9200-i2c-5-41/iout1/curr2_lcrit_alarm + - ucd9200-i2c-5-41/iout1/curr2_crit_alarm + temp: + - coretemp-isa-0000/Physical id 0/temp1_crit_alarm + - coretemp-isa-0000/Core 0/temp2_crit_alarm + - coretemp-isa-0000/Core 1/temp3_crit_alarm + - dps460-i2c-10-59/temp1/temp1_max_alarm + - dps460-i2c-10-59/temp1/temp1_min_alarm + - dps460-i2c-10-59/temp1/temp1_crit_alarm + - dps460-i2c-10-59/temp1/temp1_lcrit_alarm + - dps460-i2c-10-59/temp2/temp2_max_alarm + - dps460-i2c-10-59/temp2/temp2_min_alarm + - dps460-i2c-10-59/temp2/temp2_crit_alarm + - dps460-i2c-10-59/temp2/temp2_lcrit_alarm + - dps460-i2c-10-59/temp3/temp3_max_alarm + - dps460-i2c-10-59/temp3/temp3_min_alarm + - dps460-i2c-10-59/temp3/temp3_crit_alarm + - dps460-i2c-10-59/temp3/temp3_lcrit_alarm + - dps460-i2c-10-58/temp1/temp1_max_alarm + - dps460-i2c-10-58/temp1/temp1_min_alarm + - dps460-i2c-10-58/temp1/temp1_crit_alarm + - dps460-i2c-10-58/temp1/temp1_lcrit_alarm + - dps460-i2c-10-58/temp2/temp2_max_alarm + - dps460-i2c-10-58/temp2/temp2_min_alarm + - dps460-i2c-10-58/temp2/temp2_crit_alarm + - dps460-i2c-10-58/temp2/temp2_lcrit_alarm + - dps460-i2c-10-58/temp3/temp3_max_alarm + - dps460-i2c-10-58/temp3/temp3_min_alarm + - dps460-i2c-10-58/temp3/temp3_crit_alarm + - dps460-i2c-10-58/temp3/temp3_lcrit_alarm + - ucd9200-i2c-5-27/UCD1 Temp/temp1_max_alarm + - ucd9200-i2c-5-27/UCD1 Temp/temp1_crit_alarm + - ucd9200-i2c-5-27/UCD1 Temp2/temp2_max_alarm + - ucd9200-i2c-5-27/UCD1 Temp2/temp2_crit_alarm + - ucd9200-i2c-5-27/temp3/temp3_max_alarm + - ucd9200-i2c-5-27/temp3/temp3_crit_alarm + - ucd9200-i2c-5-41/UCD2 Temp1/temp1_max_alarm + - ucd9200-i2c-5-41/UCD2 Temp1/temp1_crit_alarm + - ucd9200-i2c-5-41/UCD2 Temp2/temp2_max_alarm + - ucd9200-i2c-5-41/UCD2 Temp2/temp2_crit_alarm + compares: + fan: + - - spectrum-i2c-2-48/fan1/fan1_input + - spectrum-i2c-2-48/fan1/fan1_max + - - spectrum-i2c-2-48/fan1/fan1_min + - spectrum-i2c-2-48/fan1/fan1_input + - - spectrum-i2c-2-48/fan2/fan2_input + - spectrum-i2c-2-48/fan2/fan2_max + - - spectrum-i2c-2-48/fan2/fan2_min + - spectrum-i2c-2-48/fan2/fan2_input + - - spectrum-i2c-2-48/fan3/fan3_input + - spectrum-i2c-2-48/fan3/fan3_max + - - spectrum-i2c-2-48/fan3/fan3_min + - spectrum-i2c-2-48/fan3/fan3_input + - - spectrum-i2c-2-48/fan4/fan4_input + - spectrum-i2c-2-48/fan4/fan4_max + - - spectrum-i2c-2-48/fan4/fan4_min + - spectrum-i2c-2-48/fan4/fan4_input + - - spectrum-i2c-2-48/fan5/fan5_input + - spectrum-i2c-2-48/fan5/fan5_max + - - spectrum-i2c-2-48/fan5/fan5_min + - spectrum-i2c-2-48/fan5/fan5_input + - - spectrum-i2c-2-48/fan6/fan6_input + - spectrum-i2c-2-48/fan6/fan6_max + - - spectrum-i2c-2-48/fan6/fan6_min + - spectrum-i2c-2-48/fan6/fan6_input + - - spectrum-i2c-2-48/fan7/fan7_input + - spectrum-i2c-2-48/fan7/fan7_max + - - spectrum-i2c-2-48/fan7/fan7_min + - spectrum-i2c-2-48/fan7/fan7_input + - - spectrum-i2c-2-48/fan8/fan8_input + - spectrum-i2c-2-48/fan8/fan8_max + - - spectrum-i2c-2-48/fan8/fan8_min + - spectrum-i2c-2-48/fan8/fan8_input + power: + - - mlnxa2dswb-i2c-5-6d/1.8V_sw_spc/in1_input + - mlnxa2dswb-i2c-5-6d/1.8V_sw_spc/in1_max + - - mlnxa2dswb-i2c-5-6d/1.8V_sw_spc/in1_min + - mlnxa2dswb-i2c-5-6d/1.8V_sw_spc/in1_input + - - mlnxa2dmnb-i2c-15-6d/ddr3_0.675/in1_input + - mlnxa2dmnb-i2c-15-6d/ddr3_0.675/in1_max + - - mlnxa2dmnb-i2c-15-6d/ddr3_0.675/in1_min + - mlnxa2dmnb-i2c-15-6d/ddr3_0.675/in1_input + - - mlnxa2dmnb-i2c-15-6d/cpu_0.9/in2_input + - mlnxa2dmnb-i2c-15-6d/cpu_0.9/in2_max + - - mlnxa2dmnb-i2c-15-6d/sys/in3_input + - mlnxa2dmnb-i2c-15-6d/sys/in3_max + - - mlnxa2dmnb-i2c-15-6d/sys/in3_min + - mlnxa2dmnb-i2c-15-6d/sys/in3_input + - - mlnxa2dmnb-i2c-15-6d/cpu_1.8/in4_input + - mlnxa2dmnb-i2c-15-6d/cpu_1.8/in4_max + - - mlnxa2dmnb-i2c-15-6d/cpu_1.8/in4_min + - mlnxa2dmnb-i2c-15-6d/cpu_1.8/in4_input + - - mlnxa2dmnb-i2c-15-6d/cpu_pch_1.05/in5_input + - mlnxa2dmnb-i2c-15-6d/cpu_pch_1.05/in5_max + - - mlnxa2dmnb-i2c-15-6d/cpu_pch_1.05/in5_min + - mlnxa2dmnb-i2c-15-6d/cpu_pch_1.05/in5_input + - - mlnxa2dmnb-i2c-15-6d/cpu_1.05/in6_input + - mlnxa2dmnb-i2c-15-6d/cpu_1.05/in6_max + - - mlnxa2dmnb-i2c-15-6d/cpu_1.05/in6_min + - mlnxa2dmnb-i2c-15-6d/cpu_1.05/in6_input + - - mlnxa2dmnb-i2c-15-6d/ddr3_1.35/in7_input + - mlnxa2dmnb-i2c-15-6d/ddr3_1.35/in7_max + - - mlnxa2dmnb-i2c-15-6d/ddr3_1.35/in7_min + - mlnxa2dmnb-i2c-15-6d/ddr3_1.35/in7_input + - - mlnxa2dmnb-i2c-15-6d/usb_5/in8_input + - mlnxa2dmnb-i2c-15-6d/usb_5/in8_max + - - mlnxa2dmnb-i2c-15-6d/usb_5/in8_min + - mlnxa2dmnb-i2c-15-6d/usb_5/in8_input + - - mlnxa2dmnb-i2c-15-6d/lan_1.05/in9_input + - mlnxa2dmnb-i2c-15-6d/lan_1.05/in9_max + - - mlnxa2dmnb-i2c-15-6d/lan_1.05/in9_min + - mlnxa2dmnb-i2c-15-6d/lan_1.05/in9_input + temp: + - - acpitz-virtual-0/temp1/temp1_input + - acpitz-virtual-0/temp1/temp1_crit + - - acpitz-virtual-0/temp2/temp2_input + - acpitz-virtual-0/temp2/temp2_crit + - - spectrum-i2c-2-48/temp1/temp1_input + - spectrum-i2c-2-48/temp1/temp1_max + - - spectrum-i2c-2-48/temp1/temp1_min + - spectrum-i2c-2-48/temp1/temp1_input + - - lm75-i2c-7-4a/Ambient Port Temp/temp1_input + - lm75-i2c-7-4a/Ambient Port Temp/temp1_max_hyst + - - lm75-i2c-17-49/temp1/temp1_input + - lm75-i2c-17-49/temp1/temp1_max_hyst + non_zero: + fan: [] + power: + - ucd9200-i2c-5-27/pout1/power2_input + - ucd9200-i2c-5-27/pout2/power3_input + - ucd9200-i2c-5-41/pout1/power2_input + temp: [] + psu_skips: + dps460-i2c-10-58: + number: 2 + side: right + skip_list: + - dps460-i2c-10-58 + dps460-i2c-10-59: + number: 1 + side: left + skip_list: + - dps460-i2c-10-59 + + Arista-7050-QX32: + alarms: + fan: [] + power: + - pmbus-i2c-3-4e/vout1/in1_min_alarm + - pmbus-i2c-3-4e/vout1/in1_max_alarm + - pmbus-i2c-3-4e/vout1/in1_lcrit_alarm + - pmbus-i2c-3-4e/vout1/in1_crit_alarm + - pmbus-i2c-5-58/vin/in1_min_alarm + - pmbus-i2c-5-58/vin/in1_max_alarm + - pmbus-i2c-5-58/vin/in1_crit_alarm + - pmbus-i2c-5-58/vout1/in3_min_alarm + - pmbus-i2c-5-58/vout1/in3_max_alarm + - pmbus-i2c-5-58/vout1/in3_lcrit_alarm + - pmbus-i2c-5-58/vout1/in3_crit_alarm + - pmbus-i2c-5-58/pin/power1_alarm + - pmbus-i2c-5-58/pout1/power2_cap_alarm + - pmbus-i2c-5-58/pout1/power2_max_alarm + - pmbus-i2c-5-58/pout1/power2_crit_alarm + - pmbus-i2c-5-58/iin/curr1_max_alarm + - pmbus-i2c-5-58/iin/curr1_crit_alarm + - pmbus-i2c-5-58/iout1/curr2_max_alarm + - pmbus-i2c-5-58/iout1/curr2_lcrit_alarm + - pmbus-i2c-5-58/iout1/curr2_crit_alarm + - pmbus-i2c-6-58/vin/in1_min_alarm + - pmbus-i2c-6-58/vin/in1_max_alarm + - pmbus-i2c-6-58/vin/in1_lcrit_alarm + - pmbus-i2c-6-58/vin/in1_crit_alarm + - pmbus-i2c-6-58/vout1/in3_min_alarm + - pmbus-i2c-6-58/vout1/in3_max_alarm + - pmbus-i2c-6-58/vout1/in3_lcrit_alarm + - pmbus-i2c-6-58/vout1/in3_crit_alarm + - pmbus-i2c-6-58/iin/curr1_max_alarm + - pmbus-i2c-6-58/iin/curr1_crit_alarm + - pmbus-i2c-6-58/iout1/curr2_max_alarm + - pmbus-i2c-6-58/iout1/curr2_lcrit_alarm + - pmbus-i2c-6-58/iout1/curr2_crit_alarm + - pmbus-i2c-7-4e/vout1/in1_min_alarm + - pmbus-i2c-7-4e/vout1/in1_max_alarm + - pmbus-i2c-7-4e/vout1/in1_lcrit_alarm + - pmbus-i2c-7-4e/vout1/in1_crit_alarm + + temp: + - pmbus-i2c-5-58/Power Supply 1 Sensor 1/temp1_max_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 1/temp1_min_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 1/temp1_crit_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 1/temp1_lcrit_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 2/temp2_max_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 2/temp2_min_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 2/temp2_crit_alarm + - pmbus-i2c-5-58/Power Supply 1 Sensor 2/temp2_lcrit_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 1/temp1_max_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 1/temp1_min_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 1/temp1_crit_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 1/temp1_lcrit_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 2/temp2_max_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 2/temp2_min_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 2/temp2_crit_alarm + - pmbus-i2c-6-58/Power Supply 2 Sensor 2/temp2_lcrit_alarm + + compares: + fan: [] + power: + - - pmbus-i2c-3-4e/vout1/in1_input + - pmbus-i2c-3-4e/vout1/in1_max + - - pmbus-i2c-5-58/vin/in1_input + - pmbus-i2c-5-58/vin/in1_max + - - pmbus-i2c-5-58/vout1/in3_input + - pmbus-i2c-5-58/vout1/in3_max + - - pmbus-i2c-5-58/pin/power1_input + - pmbus-i2c-5-58/pin/power1_max + - - pmbus-i2c-5-58/pout1/power2_input + - pmbus-i2c-5-58/pout1/power2_max + - - pmbus-i2c-5-58/iin/curr1_input + - pmbus-i2c-5-58/iin/curr1_max + - - pmbus-i2c-5-58/iout1/curr2_input + - pmbus-i2c-5-58/iout1/curr2_max + - - pmbus-i2c-7-4e/vout1/in1_input + - pmbus-i2c-7-4e/vout1/in1_max + temp: + - - k10temp-pci-00c3/Cpu temp sensor/temp1_input + - k10temp-pci-00c3/Cpu temp sensor/temp1_max + - - lm73-i2c-3-48/Rear Temp Sensor/temp1_input + - lm73-i2c-3-48/Rear Temp Sensor/temp1_max + - - lm86-i2c-2-4c/Board Temp Sensor/temp1_input + - lm86-i2c-2-4c/Board Temp Sensor/temp1_max + - - lm86-i2c-2-4c/Front-panel Temp Sensor/temp2_input + - lm86-i2c-2-4c/Front-panel Temp Sensor/temp2_max + - - pmbus-i2c-3-4e/Power Controller Sensor 1/temp1_input + - pmbus-i2c-3-4e/Power Controller Sensor 1/temp1_max + - - pmbus-i2c-3-4e/Power Controller Sensor 2/temp2_input + - pmbus-i2c-3-4e/Power Controller Sensor 2/temp2_max + - - pmbus-i2c-5-58/Power Supply 1 Sensor 1/temp1_input + - pmbus-i2c-5-58/Power Supply 1 Sensor 1/temp1_max + - - pmbus-i2c-5-58/Power Supply 1 Sensor 2/temp2_input + - pmbus-i2c-5-58/Power Supply 1 Sensor 2/temp2_max + - - pmbus-i2c-6-58/Power Supply 2 Sensor 1/temp1_input + - pmbus-i2c-6-58/Power Supply 2 Sensor 1/temp1_max + - - pmbus-i2c-6-58/Power Supply 2 Sensor 2/temp2_input + - pmbus-i2c-6-58/Power Supply 2 Sensor 2/temp2_max + + non_zero: + fan: + - pmbus-i2c-5-58/fan1/fan1_input + - pmbus-i2c-6-58/fan1/fan1_input + power: + - pmbus-i2c-6-58/vcap/in2_input + - pmbus-i2c-5-58/vcap/in2_input + temp: [] + + psu_skips: {} diff --git a/ansible/group_vars/sonic/vars b/ansible/group_vars/sonic/vars index 641c21f6e05..8154122deb3 100644 --- a/ansible/group_vars/sonic/vars +++ b/ansible/group_vars/sonic/vars @@ -1,9 +1,4 @@ ansible_ssh_user: admin -ansible_ssh_pass: YourPaSsWoRd -ansible_become_pass: YourPaSsWoRd -sonicadmin_user: admin -sonicadmin_password: YourPaSsWoRd -sonicadmin_initial_password: YourPaSsWoRd sonic_version: "v2" @@ -22,8 +17,17 @@ sensor_hwskus: [ "ACS-MSN2700", "Force10-S6000" ] ## 1. http://stackoverflow.com/questions/9254178/is-there-yaml-syntax-for-sharing-part-of-a-list-or-map ## 2. https://groups.google.com/forum/#!msg/ansible-project/M-FNUK9Wz98/gH63Ka4hDAAJ +sswsyncd_docker_volumes_dict: + "/etc/ssw/:/etc/ssw/:ro": + "/etc/sonic/:/etc/sonic/:ro": + "/etc/network/interfaces:/etc/network/interfaces:ro": + "/var/run/docker-syncd:/var/run/sswsyncd": + +sswsyncd_docker_volumes: "{{ sswsyncd_docker_volumes_dict.keys() }}" + syncd_docker_volumes_dict: - "/host/machine.conf:/etc/machine.conf:ro": + "/host/machine.conf:/etc/machine.conf": + "/var/run/docker-syncd:/var/run/sswsyncd": "/etc/sonic/:/etc/sonic/:ro": syncd_docker_volumes: "{{ syncd_docker_volumes_dict.keys() }}" @@ -36,20 +40,3 @@ orchagent_docker_volumes_dict: "/host/machine.conf:/host/machine.conf": orchagent_docker_volumes: "{{ orchagent_docker_volumes_dict.keys() }}" - -sonic_apt_repo: "http://packages.microsoft.com/repos/sonic-dev/" -apt_repo: "http://debian-archive.trafficmanager.net/debian/" -apt_default_release: "*" - -# ntp variables -ntp_servers: ['10.0.0.1', '10.0.0.2'] - -# syslog variables -syslog_servers: ['10.0.0.5', '10.0.0.6'] - -# dns variables -dns_servers: ['10.0.0.5', '10.0.0.6'] - -# snmp variables -snmp_rocommunity: public -snmp_location: testlab diff --git a/ansible/str b/ansible/lab similarity index 100% rename from ansible/str rename to ansible/lab diff --git a/ansible/library/conn_graph_facts.py b/ansible/library/conn_graph_facts.py index 4fab63625cd..40c8e1765fd 100644 --- a/ansible/library/conn_graph_facts.py +++ b/ansible/library/conn_graph_facts.py @@ -68,8 +68,7 @@ ''' -LAB_CONNECTION_GRAPH_FILE = 'starlab_connection_graph.xml' -LAB_SERVER_CONNECTION = 'sonic_server_links.yml' +LAB_CONNECTION_GRAPH_FILE = 'lab_connection_graph.xml' LAB_GRAPHFILE_PATH = 'files/' class Parse_Lab_Graph(): @@ -163,44 +162,6 @@ def parse_graph(self): self.devices = deviceinfo self.vlanport = devicel2info - def parse_server_links(self, server_link): - """ - lab graph file only contains physical links information between all fanout switches, Sonic devices and servers - to connect server docker to a Sonic device through vlan switching, information is in sonic_server_links.yml - grab each server external interface through host_vars/server.yml file - read server docker to Sonic link yaml file to figure out each server port vlan range - """ - with open(server_link) as f: - server_linkdict = yaml.load(f) - for server in server_linkdict: - ### get server external interface from default configured host_vars - server_hostfile = 'host_vars/'+server.upper()+'.yml' - with open(server_hostfile) as hf: - server_hostdict = yaml.load(hf) - self.server[server]['ext_intf'] = server_hostdict['external_iface'] - self.server[server]['vlanlist'] = [] - for dut in server_linkdict[server]: - self.server[server]['vlanlist'] += self.get_host_vlan(dut)['VlanList'] - for serv in self.server: - self.server[serv]['vlanrange'] = self.convert_list2range(self.server[serv]['vlanlist']) - self.fanoutroot_server_ports() - - def fanoutroot_server_ports(self): - """ - configure each server port on root fanout switch to correct vlan range after getting server connections - """ - for dev in self.devices: - if 'fanoutroot' in self.devices[dev]['Type'].lower(): - fanoutroot = dev - if fanoutroot is not None: - for link in self.links[fanoutroot]: - if 'acs-serv-' in self.links[fanoutroot][link]['peerdevice']: - server = self.links[fanoutroot][link]['peerdevice'] - if self.links[fanoutroot][link]['peerport'] == self.server[server]['ext_intf']: - self.vlanport[fanoutroot][link]['vlanids'] = ','.join(self.server[server]['vlanrange']) - self.vlanport[fanoutroot][link]['vlanlist'] = self.server[server]['vlanlist'] - - def convert_list2range(self, l): """ common module to convert a list to range for easier vlan configuration generation @@ -281,7 +242,6 @@ def main(): try: lab_graph = Parse_Lab_Graph(LAB_GRAPHFILE_PATH+LAB_CONNECTION_GRAPH_FILE) lab_graph.parse_graph() - lab_graph.parse_server_links(LAB_GRAPHFILE_PATH+LAB_SERVER_CONNECTION) dev = lab_graph.get_host_device_info(hostname) if dev is None: module.fail_json(msg="cannot find info for "+hostname) @@ -300,11 +260,10 @@ def main(): def debug_main(): # host = 'str-7260-11' -# host = 'str-s6000-on-4' - host = 'str-7260-01' - lab_graph = Parse_Lab_Graph(LAB_CONNECTION_GRAPH_FILE) + host = 'str-s6000-on-6' +# host = 'str-7260-01' + lab_graph = Parse_Lab_Graph(LAB_GRAPHFILE_PATH+LAB_CONNECTION_GRAPH_FILE) lab_graph.parse_graph() - lab_graph.parse_server_links(LAB_SERVER_CONNECTION) dev = lab_graph.get_host_device_info(host) results = {} results['device_info'] = lab_graph.get_host_device_info(host) @@ -321,6 +280,5 @@ def debug_main(): from ansible.module_utils.basic import * if __name__== "__main__": main() -# debug_main() diff --git a/ansible/library/minigraph_facts.py b/ansible/library/minigraph_facts.py index 4e0ae00c56f..d22b9c53bc5 100644 --- a/ansible/library/minigraph_facts.py +++ b/ansible/library/minigraph_facts.py @@ -10,7 +10,6 @@ from collections import defaultdict from natsort import natsorted - from lxml import etree as ET from lxml.etree import QName @@ -47,10 +46,12 @@ class minigraph_encoder(json.JSONEncoder): def default(self, obj): - if isinstance(obj, (ipaddress.IPv4Network, ipaddress.IPv6Network, ipaddress.IPv4Address, ipaddress.IPv6Address)): + if isinstance(obj, + (ipaddress.IPv4Network, ipaddress.IPv6Network, ipaddress.IPv4Address, ipaddress.IPv6Address)): return str(obj) return json.JSONEncoder.default(self, obj) - + + def parse_png(png, hname): neighbors = {} devices = {} @@ -71,9 +72,14 @@ def parse_png(png, hname): startport = link.find(str(QName(ns, "StartPort"))).text if enddevice == hname: + if port_alias_map.has_key(endport): + endport = port_alias_map[endport] neighbors[endport] = {'name': startdevice, 'port': startport} else: + if port_alias_map.has_key(startport): + startport = port_alias_map[startport] neighbors[startport] = {'name': enddevice, 'port': endport} + if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): lo_addr = None @@ -113,7 +119,6 @@ def parse_png(png, hname): elif node.tag == str(QName(ns, "EndDevice")): mgmt_dev = node.text - return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port) @@ -125,9 +130,12 @@ def parse_dpg(dpg, hname): ipintfs = child.find(str(QName(ns, "IPInterfaces"))) intfs = [] - vlan_map = {} for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))): - intfname = ipintf.find(str(QName(ns, "AttachTo"))).text + intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text + if port_alias_map.has_key(intfalias): + intfname = port_alias_map[intfalias] + else: + intfname = intfalias ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text ipn = ipaddress.IPNetwork(ipprefix) ipaddr = ipn.ip @@ -135,52 +143,32 @@ def parse_dpg(dpg, hname): addr_bits = ipn.max_prefixlen subnet = ipaddress.IPNetwork(str(ipn.network) + '/' + str(prefix_len)) ipmask = ipn.netmask - + intf = {'addr': ipaddr, 'subnet': subnet} if isinstance(ipn, ipaddress.IPv4Network): intf['mask'] = ipmask else: intf['mask'] = str(prefix_len) + intf.update({'attachto': intfname, 'prefixlen': int(prefix_len)}) - if intfname[0:4] == "Vlan": - if intfname in vlan_map: - vlan_map[intfname].append(intf) - + # TODO: remove peer_addr after dependency removed + ipaddr_val = int(ipn.ip) + peer_addr_val = None + if int(prefix_len) == addr_bits - 2: + if ipaddr_val & 0x3 == 1: + peer_addr_val = ipaddr_val + 1 else: - vlan_map[intfname] = [intf] - else: - intf.update({'name': intfname, 'prefixlen': int(prefix_len)}) - - if port_alias_map.has_key(intfname): - intf['alias'] = port_alias_map[intfname] + peer_addr_val = ipaddr_val - 1 + elif int(prefix_len) == addr_bits - 1: + if ipaddr_val & 0x1 == 0: + peer_addr_val = ipaddr_val + 1 else: - intf['alias'] = intfname + peer_addr_val = ipaddr_val - 1 - # TODO: remove peer_addr after dependency removed - ipaddr_val = int(ipn.ip) - peer_addr_val = None - if int(prefix_len) == addr_bits - 2: - if ipaddr_val & 0x3 == 1: - peer_addr_val = ipaddr_val + 1 - else: - peer_addr_val = ipaddr_val - 1 - elif int(prefix_len) == addr_bits - 1: - if ipaddr_val & 0x1 == 0: - peer_addr_val = ipaddr_val + 1 - else: - peer_addr_val = ipaddr_val - 1 - - if peer_addr_val is not None: - intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val) - intfs.append(intf) - - pcintfs = child.find(str(QName(ns, "PortChannelInterfaces"))) - pc_intfs = [] - for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))): - pcintfname = pcintf.find(str(QName(ns, "Name"))).text - pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text - pcmbr_list = pcintfmbr.split(';', 1) - pc_intfs.append({'name': pcintfname, 'members': pcmbr_list}) + if peer_addr_val is not None: + intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val) + intfs.append(intf) + ports[intfname] = {'name': intfname, 'alias': intfalias} lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces"))) lo_intfs = [] @@ -209,20 +197,53 @@ def parse_dpg(dpg, hname): gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1) mgmt_intf = {'addr': ipaddr, 'prefixlen': prefix_len, 'mask': ipmask, 'gwaddr': gwaddr} + pcintfs = child.find(str(QName(ns, "PortChannelInterfaces"))) + pc_intfs = [] + pcs = {} + for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))): + pcintfname = pcintf.find(str(QName(ns, "Name"))).text + pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text + pcmbr_list = pcintfmbr.split(';', 1) + for i, member in enumerate(pcmbr_list): + pcmbr_list[i] = port_alias_map[member] + ports[port_alias_map[member]] = {'name': port_alias_map[member], 'alias': member} + pcs[pcintfname] = {'name': pcintfname, 'members': pcmbr_list} + ports.pop(pcintfname) + vlanintfs = child.find(str(QName(ns, "VlanInterfaces"))) vlan_intfs = [] + vlans = {} for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))): vintfname = vintf.find(str(QName(ns, "Name"))).text vlanid = vintf.find(str(QName(ns, "VlanID"))).text vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text vmbr_list = vintfmbr.split(';') + for i, member in enumerate(vmbr_list): + vmbr_list[i] = port_alias_map[member] + ports[port_alias_map[member]] = {'name': port_alias_map[member], 'alias': member} vlan_attributes = {'name': vintfname, 'members': vmbr_list, 'vlanid': vlanid} - for addrtuple in vlan_map.get(vintfname, []): - vlan_attributes.update(addrtuple) - vlan_intfs.append(copy.deepcopy(vlan_attributes)) - - return intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs - return None, None, None, None, None + vlans[vintfname] = vlan_attributes + ports.pop(vintfname) + + aclintfs = child.find(str(QName(ns, "AclInterfaces"))) + acls = {} + for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))): + aclname = aclintf.find(str(QName(ns, "InAcl"))).text + aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';') + acl_intfs = [] + for member in aclattach: + member = member.strip() + if pcs.has_key(member): + acl_intfs.extend(pcs[member]['members']) # For ACL attaching to port channels, we break them into port channel members + elif vlans.has_key(member): + print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a Vlan interface, which is currently not supported" + elif port_alias_map.has_key(member): + acl_intfs.append(port_alias_map[member]) + if acl_intfs: + acls[aclname] = acl_intfs + + return intfs, lo_intfs, mgmt_intf, vlans, pcs, acls + return None, None, None, None, None, None def parse_cpg(cpg, hname): bgp_sessions = [] @@ -260,10 +281,12 @@ def parse_cpg(cpg, hname): return bgp_sessions, myasn + def parse_meta(meta, hname): syslog_servers = [] dhcp_servers = [] ntp_servers = [] + mgmt_routes = [] device_metas = meta.find(str(QName(ns, "Devices"))) for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): if device.find(str(QName(ns1, "Name"))).text == hname: @@ -278,7 +301,9 @@ def parse_meta(meta, hname): ntp_servers = value_group elif name == "SyslogResources": syslog_servers = value_group - return syslog_servers, dhcp_servers, ntp_servers + elif name == "ForcedMgmtRoutes": + mgmt_routes = value_group + return syslog_servers, dhcp_servers, ntp_servers, mgmt_routes def get_console_info(devices, dev, port): @@ -296,6 +321,7 @@ def get_console_info(devices, dev, port): return ret_val + def get_mgmt_info(devices, dev, port): for k, v in devices.items(): if k == dev: @@ -345,9 +371,9 @@ def reconcile_mini_graph_locations(filename, hostname): if os.path.exists(mini_graph_path) and file_age(mini_graph_path) < ANSIBLE_USER_MINIGRAPH_MAX_AGE: # found a cached mini-graph, load it. root = ET.parse(mini_graph_path).getroot() - return mini_graph_path, root + def parse_xml(filename, hostname): mini_graph_path, root = reconcile_mini_graph_locations(filename, hostname) @@ -359,18 +385,25 @@ def parse_xml(filename, hostname): intfs = None vlan_intfs = None pc_intfs = None + vlans = None + pcs = None mgmt_intf = None lo_intf = None neighbors = None devices = None + hostname = None syslog_servers = [] dhcp_servers = [] ntp_servers = [] + mgmt_routes = [] hwsku_qn = QName(ns, "HwSku") + hostname_qn = QName(ns, "Hostname") for child in root: if child.tag == str(hwsku_qn): hwsku = child.text + if child.tag == str(hostname_qn): + hostname = child.text # port_alias_map maps ngs port name to sonic port name if hwsku == "Force10-S6000": @@ -385,13 +418,18 @@ def parse_xml(filename, hostname): port_alias_map["Ethernet%d/1" % i] = "Ethernet%d" % ((i - 1) * 4) for i in range(25, 33): port_alias_map["Ethernet%d" % i] = "Ethernet%d" % ((i - 1) * 4) + elif hwsku == "Arista-7050-QX-32S": + for i in range(6, 29): + port_alias_map["Ethernet%d/1" % i] = "Ethernet%d" % ((i - 1) * 4) + for i in range(1,5) + range(29, 37): + port_alias_map["Ethernet%d" % i] = "Ethernet%d" % ((i - 1) * 4) else: for i in range(0, 128, 4): port_alias_map["Ethernet%d" % i] = "Ethernet%d" % i for child in root: if child.tag == str(QName(ns, "DpgDec")): - (intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs) = parse_dpg(child, hostname) + (intfs, lo_intfs, mgmt_intf, vlans, pcs, acls) = parse_dpg(child, hostname) elif child.tag == str(QName(ns, "CpgDec")): (bgp_sessions, bgp_asn) = parse_cpg(child, hostname) elif child.tag == str(QName(ns, "PngDec")): @@ -399,22 +437,7 @@ def parse_xml(filename, hostname): elif child.tag == str(QName(ns, "UngDec")): (u_neighbors, u_devices, _, _, _, _) = parse_png(child, hostname) elif child.tag == str(QName(ns, "MetadataDeclaration")): - (syslog_servers, dhcp_servers, ntp_servers) = parse_meta(child, hostname) - - # Replace port with alias in Vlan interfaces members - if vlan_intfs is not None: - for vlan in vlan_intfs: - for i,member in enumerate(vlan['members']): - vlan['members'][i] = port_alias_map[member] - # Convert vlan members into a space-delimited string - vlan['members'] = " ".join(vlan['members']) - - # Replace port with alias in port channel interfaces members - if pc_intfs is not None: - for pc in pc_intfs: - for i,member in enumerate(pc['members']): - pc['members'][i] = port_alias_map[member] - + (syslog_servers, dhcp_servers, ntp_servers, mgmt_routes) = parse_meta(child, hostname) # Create port index map. Since we currently output a mix of NGS names # and SONiC mapped names, we include both in this map. @@ -463,30 +486,49 @@ def parse_xml(filename, hostname): results['minigraph_bgp'] = sorted(bgp_sessions, key=lambda x: x['addr']) results['minigraph_bgp_asn'] = bgp_asn # TODO: sort does not work properly on all interfaces of varying lengths. Need to sort by integer group(s). - results['minigraph_interfaces'] = sorted(intfs, key=lambda x: x['name']) - results['minigraph_vlan_interfaces'] = vlan_intfs - results['minigraph_portchannel_interfaces'] = pc_intfs + + phyport_intfs = [] + vlan_intfs = [] + pc_intfs = [] + for intf in intfs: + intfname = intf['attachto'] + if intfname[0:4] == 'Vlan': + vlan_intfs.append(intf) + elif intfname[0:11] == 'PortChannel': + pc_intfs.append(intf) + else: + phyport_intfs.append(intf) + + results['minigraph_interfaces'] = sorted(phyport_intfs, key=lambda x: x['attachto']) + results['minigraph_vlan_interfaces'] = sorted(vlan_intfs, key=lambda x: x['attachto']) + results['minigraph_portchannel_interfaces'] = sorted(pc_intfs, key=lambda x: x['attachto']) + results['minigraph_ports'] = ports + results['minigraph_vlans'] = vlans + results['minigraph_portchannels'] = pcs results['minigraph_mgmt_interface'] = mgmt_intf results['minigraph_lo_interfaces'] = lo_intfs + results['minigraph_acls'] = acls results['minigraph_neighbors'] = neighbors results['minigraph_devices'] = devices results['minigraph_underlay_neighbors'] = u_neighbors results['minigraph_underlay_devices'] = u_devices - # note - this may include files under acs/ansible/minigraph, or those under the default cache folder. - # (see ANSIBLE_USER_MINIGRAPH_PATH at the top of the module) - results['minigraph_as_xml'] = mini_graph_path - results['minigraph_console'] = get_console_info(devices, console_dev, console_port) - results['minigraph_mgmt'] = get_mgmt_info(devices, mgmt_dev, mgmt_port) results['minigraph_port_indices'] = port_index_map results['minigraph_map_sonic_to_ngs'] = iface_map_sonic_to_ngs results['minigraph_map_ngs_to_sonic'] = iface_map_ngs_to_sonic + results['minigraph_as_xml'] = mini_graph_path + if devices != None: + results['minigraph_console'] = get_console_info(devices, console_dev, console_port) + results['minigraph_mgmt'] = get_mgmt_info(devices, mgmt_dev, mgmt_port) + results['minigraph_hostname'] = hostname + results['inventory_hostname'] = hostname results['syslog_servers'] = syslog_servers results['dhcp_servers'] = dhcp_servers results['ntp_servers'] = ntp_servers + results['forced_mgmt_routes'] = mgmt_routes return results - +ports = {} port_alias_map = {} def main(): @@ -538,4 +580,3 @@ def print_parse_xml(hostname): if __name__ == "__main__": main() #debug_main() - diff --git a/ansible/library/syslog_server.py b/ansible/library/syslog_server.py deleted file mode 100644 index 9f5575b8b55..00000000000 --- a/ansible/library/syslog_server.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/python - -DOCUMENTATION = ''' ---- -module: syslog_server -version_added: "1.0" -author: John Arnold (johnar@microsoft.com) -short_description: Receive Syslog messages -description: - - Start a Syslog listener, receive syslog messages and return them. -options: -''' - -EXAMPLES = ''' -# Receive Syslog messages -- name: Receive Syslog Messages - syslog_server: -''' - -from ansible.module_utils.basic import * -from collections import defaultdict -import socket -import struct -import re -import json -import time -import SocketServer -import threading - - -#HOST, PORT = "0.0.0.0", 5514 - -queuedOutput = [] - - -class ThreadedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer): - pass - - -class ThreadedUDPRequestHandler(SocketServer.BaseRequestHandler): - - def handle(self): - data = bytes.decode(self.request[0].strip()) - socket = self.request[1] - - newLogString = "%s %s %s\n" % ( time.time(), self.client_address[0], data) - - global queuedOutput - queuedOutput.append(newLogString) - -def main(): - module = AnsibleModule( - argument_spec=dict( - timeout=dict(required=False, default=30), - port=dict(required=False, default=5514), - host=dict(required=False, default="0.0.0.0") - ), - supports_check_mode=False) - - args = module.params - - try: - server = ThreadedUDPServer((args['host'],int(args['port'])), ThreadedUDPRequestHandler) - server.allow_reuse_address=True - - server_thread = threading.Thread(target=server.serve_forever) - server_thread.daemon = True - server_thread.start() - - time.sleep(float(args['timeout'])) - server.shutdown() - - except Exception, e: - module.fail_json(msg = str(e)) - - Tree = lambda: defaultdict(Tree) - results = Tree() - - global queuedOutput - results['syslog_messages'] = queuedOutput - - module.exit_json(ansible_facts=results) - -if __name__ == "__main__": - main() - diff --git a/ansible/plugins/connection/switch.py b/ansible/plugins/connection/switch.py index 2307395d065..47e25db26ac 100644 --- a/ansible/plugins/connection/switch.py +++ b/ansible/plugins/connection/switch.py @@ -93,17 +93,28 @@ def _spawn_connect(self): if attempt == len(self.login['user']): raise AnsibleError("none of the passwords in the book works") - self.hname = client.before.split()[-1] - self.hname = self.hname.replace("(", "[(]") - self.hname = self.hname.replace(")", "[)]") + self.before_backup = client.before.split() # determine the sku - client.sendline('show version | no-more') + client.sendline('show version') client.expect(['#', '>']) if 'Arista' in client.before: self.sku = 'eos' elif 'Cisco' in client.before: self.sku = 'nxos' + if 'MLNX-OS' in client.before: + self.sku = 'mlnx_os' + + if self.sku == 'mlnx_os': + self.hname = ' '.join(self.before_backup[-3:]) + self.hname = self.hname.replace("(", "[(]") + self.hname = self.hname.replace(")", "[)]") + self.hname = self.hname.replace("]", "\]") + self.hname = self.hname.replace("[", "\[") + else: + self.hname = self.before_backup[-1] + self.hname = self.hname.replace("(", "[(]") + self.hname = self.hname.replace(")", "[)]") if i == 0 and self.enable: attempt = 0 @@ -154,7 +165,7 @@ def _spawn_connect(self): client.sendline('bash') client.expect(['\$ ']) else: - raise AnsibleError("do not support shell mode for sku %s" % self.sku) + raise AnsibleError("do not support shell mode for sku %s" % self.sku) return client @@ -182,16 +193,14 @@ def exec_command(self, *args, **kwargs): # "%s(\([a-z\-]+\))?#": privileged prompt including configure mode # Prompt includes Login, Password, and yes/no for "start shell" case in Dell FTOS (launch bash shell) if not self.bash: - prompts = ["%s>" % self.hname, "%s(\([a-zA-Z0-9\/\-]+\))?#" % self.hname, '[Ll]ogin:', '[Pp]assword:', '\[(confirm )?yes\/no\]:', '\(y\/n\)\??\s?\[n\]'] + prompts = ["%s>" % self.hname, "%s.+" % self.hname, "%s(\([a-zA-Z0-9\/\-]+\))?#" % self.hname, '[Ll]ogin:', '[Pp]assword:', '\[(confirm )?yes\/no\]:', '\(y\/n\)\??\s?\[n\]'] else: if self.sku == 'nxos': # bash-3.2$ for nexus 6.5 prompts = ['bash-3\.2\$', 'bash-3\.2#'] elif self.sku == 'eos': prompts = ['\$ '] - elif self.sku == 'ftos': - prompts = ['SStk-0 # '] - + prompts.append(pexpect.EOF) stdout = "" @@ -236,4 +245,3 @@ def fetch_file(self, in_path, out_path): def close(self): self._connected = False - diff --git a/ansible/roles/sonic-common/tasks/sensors_check.yml b/ansible/roles/sonic-common/tasks/sensors_check.yml new file mode 100644 index 00000000000..6cfc6af7043 --- /dev/null +++ b/ansible/roles/sonic-common/tasks/sensors_check.yml @@ -0,0 +1,24 @@ +- name: Get platform monitor docker name + shell: docker ps -a --format '{{'{{'}}.Image{{'}} {{'}}.Names{{'}}'}}' | grep 'platform' | awk '{print $2}' + register: pmon_ps + +- set_fact: + ansible_python_interpreter: "docker exec -i {{ pmon_ps.stdout }} python" + +- name: Gather sensors + sensors_facts: checks={{ sensors_checks[minigraph_hwsku] }} + vars: + ansible_shell_type: docker + +- set_fact: + ansible_python_interpreter: "/usr/bin/python" + +- name: Output of sensors information + debug: var=vars['sensors'] + +- name: Assert no alarm + assert: { that: "{{ vars['sensors']['alarm'] }} == False" } + +- name: Show warnings + debug: var=vars['sensors']['warnings'] + when: vars['sensors']['warning'] diff --git a/ansible/roles/test/files/acstests/everflow_tb_test.py b/ansible/roles/test/files/acstests/everflow_tb_test.py index 5d575cfd8cd..96b194bf867 100644 --- a/ansible/roles/test/files/acstests/everflow_tb_test.py +++ b/ansible/roles/test/files/acstests/everflow_tb_test.py @@ -13,7 +13,7 @@ import ptf.dataplane as dataplane import ptf.testutils as testutils from ptf.base_tests import BaseTest - +from ptf.mask import Mask def reportResults(test_name): ''' @@ -66,6 +66,7 @@ def setUp(self): ''' self.dataplane = ptf.dataplane_instance + self.hwsku = self.test_params['hwsku'] self.router_mac = self.test_params['router_mac'] self.session_src_ip = self.test_params['session_src_ip'] self.session_dst_ip = self.test_params['session_dst_ip'] @@ -138,10 +139,21 @@ def runSendReceiveTest(self, pkt2send, src_port, destination_ports): #if (scapy_pkt[scapy.IP].tos >> 2) != self.session_dscp: # return False - payload = str(scapy_pkt[scapy.GRE].payload)[22:] + payload = str(scapy_pkt[scapy.GRE].payload) + + if self.hwsku in ["ACS-MSN2700", "ACS-MSN2100", "ACS-MSN2410"]: + payload = str(scapy_pkt[scapy.GRE].payload)[22:] + inner_pkt = scapy.Ether(payload) - return dataplane.match_exp_pkt(pkt2send, inner_pkt) + masked_inner_pkt = Mask(inner_pkt) + if scapy.IP in inner_pkt: + masked_inner_pkt.set_do_not_care_scapy(scapy.IP, "chksum") + + if scapy.TCP in inner_pkt: + masked_inner_pkt.set_do_not_care_scapy(scapy.TCP, "chksum") + + return dataplane.match_exp_pkt(masked_inner_pkt, pkt2send) @reportResults("Verify SRC IP match") @@ -172,13 +184,6 @@ def verifyL4DstPort(self): return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) - @reportResults("Verify ether type match") - def verifyEthertype(self): - pkt = self.base_pkt.copy() - pkt['Ethernet'].type = 0x1234 - return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) - - @reportResults("Verify IP protocol match") def verifyIpProtocol(self): pkt = self.base_pkt.copy() @@ -194,16 +199,16 @@ def verifyTcpFlags(self): @reportResults("Verify L4 SRC port range match") - def verifyL4SrcPort(self): + def verifyL4SrcPortRange(self): pkt = self.base_pkt.copy() - pkt['TCP'].sport = 0x123A + pkt['TCP'].sport = 4675 return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) @reportResults("Verify L4 DST port range match") - def verifyL4DstPort(self): + def verifyL4DstPortRange(self): pkt = self.base_pkt.copy() - pkt['TCP'].dport = 0x123A + pkt['TCP'].dport = 4675 return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) @@ -235,19 +240,16 @@ def runEverflowTests(self): if self.verifyL4DstPort(): tests_passed += 1 - if self.verifyEthertype(): - tests_passed += 1 - if self.verifyIpProtocol(): tests_passed += 1 if self.verifyTcpFlags(): tests_passed += 1 - if self.verifyL4SrcPort(): + if self.verifyL4SrcPortRange(): tests_passed += 1 - if self.verifyL4DstPort(): + if self.verifyL4DstPortRange(): tests_passed += 1 if self.verifyIpDscp(): diff --git a/ansible/roles/test/files/helpers/arp_responder.py b/ansible/roles/test/files/helpers/arp_responder.py new file mode 100644 index 00000000000..d5686c115c8 --- /dev/null +++ b/ansible/roles/test/files/helpers/arp_responder.py @@ -0,0 +1,128 @@ +import binascii +import socket +import struct +import select +import json +from fcntl import ioctl +from pprint import pprint + + +def hexdump(data): + print " ".join("%02x" % ord(d) for d in data) + +def get_if(iff, cmd): + s = socket.socket() + ifreq = ioctl(s, cmd, struct.pack("16s16x",iff)) + s.close() + + return ifreq + +def get_mac(iff): + SIOCGIFHWADDR = 0x8927 # Get hardware address + return get_if(iff, SIOCGIFHWADDR)[18:24] + + +class Interface(object): + ETH_P_ALL = 0x03 + RCV_TIMEOUT = 1000 + RCV_SIZE = 4096 + + def __init__(self, iface): + self.iface = iface + self.socket = None + self.mac_address = get_mac(iface) + + def __del__(self): + if self.socket: + self.socket.close() + + def bind(self): + self.socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(self.ETH_P_ALL)) + self.socket.bind((self.iface, 0)) + self.socket.settimeout(self.RCV_TIMEOUT) + + def handler(self): + return self.socket.fileno() + + def recv(self): + return self.socket.recv(self.RCV_SIZE) + + def send(self, data): + self.socket.send(data) + + def mac(self): + return self.mac_address + + def name(self): + return self.iface + + +class Poller(object): + def __init__(self, interfaces, responder): + self.responder = responder + self.mapping = {} + for interface in interfaces: + self.mapping[interface.handler()] = interface + + def poll(self): + handlers = self.mapping.keys() + while True: + (rdlist, _, _) = select.select(handlers, [], []) + for handler in rdlist: + self.responder.action(self.mapping[handler]) + + +class ARPResponder(object): + ARP_PKT_LEN = 60 + def __init__(self, ip_sets): + self.arp_chunk = binascii.unhexlify('08060001080006040002') # defines a part of the packet for ARP Reply + self.arp_pad = binascii.unhexlify('00' * 18) + + self.ip_sets = ip_sets + + return + + def action(self, interface): + data = interface.recv() + if len(data) != self.ARP_PKT_LEN: + return + + remote_mac, remote_ip, request_ip = self.extract_arp_info(data) + + request_ip_str = socket.inet_ntoa(request_ip) + if request_ip_str not in self.ip_sets[interface.name()]: + return + + arp_reply = self.generate_arp_reply(interface.mac(), remote_mac, request_ip, remote_ip) + interface.send(arp_reply) + + return + + def extract_arp_info(self, data): + return data[6:12], data[28:32], data[38:42] # remote_mac, remote_ip, request_ip + + def generate_arp_reply(self, local_mac, remote_mac, local_ip, remote_ip): + return remote_mac + local_mac + self.arp_chunk + local_mac + local_ip + remote_mac + remote_ip + self.arp_pad + + +def main(): + with open('/tmp/from_t1.json') as fp: + data = json.load(fp) + + ip_sets = {str(k): set(v) for k, v in data.items()} + + ifaces = [] + for iface_name in ip_sets.keys(): + iface = Interface(iface_name) + iface.bind() + ifaces.append(iface) + + resp = ARPResponder(ip_sets) + + p = Poller(ifaces, resp) + p.poll() + + return + +if __name__ == '__main__': + main() diff --git a/ansible/roles/test/files/helpers/change_mac.sh b/ansible/roles/test/files/helpers/change_mac.sh index 1104777d129..bc72109f753 100644 --- a/ansible/roles/test/files/helpers/change_mac.sh +++ b/ansible/roles/test/files/helpers/change_mac.sh @@ -8,4 +8,3 @@ do echo $i $mac ifconfig $i hw ether $mac done - diff --git a/ansible/roles/test/files/helpers/remove_ip.sh b/ansible/roles/test/files/helpers/remove_ip.sh index 12d8944217d..02ddffd7ec6 100755 --- a/ansible/roles/test/files/helpers/remove_ip.sh +++ b/ansible/roles/test/files/helpers/remove_ip.sh @@ -5,4 +5,3 @@ set -e for i in $(seq 0 31); do ip address flush dev eth$i done - diff --git a/ansible/roles/test/files/mem_check.sh b/ansible/roles/test/files/mem_check.sh new file mode 100755 index 00000000000..eeb2250bdeb --- /dev/null +++ b/ansible/roles/test/files/mem_check.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# +# mem_check.sh +# +# Check for memory leaks in Redis client output buffers +# Returns 0 if under threshold, 1 if over threshold +# + +REDIS_CLIENT_LIST_OUTPUT_FILE=/tmp/redis_client_list + +OMEM_THRESHOLD_BYTES=1048576 # 1MB + +TOTAL_OMEM_BYTES=0 + +# Save 'redis-cli client list' output to temp file +/usr/bin/redis-cli client list > $REDIS_CLIENT_LIST_OUTPUT_FILE + +# Extract 'omem' value from each line (client) +while read LINE; do + OMEM_BYTES=$(echo $LINE | sed 's/.*omem=\([0-9][0-9]*\) .*/\1/') + TOTAL_OMEM_BYTES=$((TOTAL_OMEM_BYTES += OMEM_BYTES)) +done < $REDIS_CLIENT_LIST_OUTPUT_FILE + +# Clean up +rm $REDIS_CLIENT_LIST_OUTPUT_FILE + +if [ $TOTAL_OMEM_BYTES -gt $OMEM_THRESHOLD_BYTES ]; then + exit 1 +fi + +exit 0 + diff --git a/ansible/roles/test/files/ptftests/IP_decap_test.py b/ansible/roles/test/files/ptftests/IP_decap_test.py new file mode 100644 index 00000000000..1c1ec3c734a --- /dev/null +++ b/ansible/roles/test/files/ptftests/IP_decap_test.py @@ -0,0 +1,166 @@ +''' +Description: This file contains the Decapasulation test for SONIC, to test Decapsulation of IPv4 with double and triple encapsulated packets + + Design is available in https://github.com/Azure/SONiC/wiki/IPv4-Decapsulation-test + +Precondition: Before the test start, all routes need to be defined as in the fib_info.txt file, in addition to the decap rule that need to be set as the dspc_mode +topology: SUpports t1, t1-lag and t0 topology + +Usage: Examples of how to start the test + ptf --test-dir /root/dor/ ip_decap_test_red --platform remote -t "verbose=True;fib_info='/root/fib_info.txt';lo_ip='10.1.0.32';router_mac='00:02:03:04:05:00';dscp_mode='pipe'; testbed_type='t1'" --log-dir /tmp/logs --verbose +Parameters: fib_info - The fib_info file location + lo_ip - The loop_back IP that is configured in the decap rule + router_mac - The mac of the router_mac + testbed_type - The type of testbed topology + dscp_mode - The rule for the dscp parameter in the decap packet that is configured in the JSON file ('pipe' for inner and 'uniform' for outer) + +''' + +#--------------------------------------------------------------------- +# Global imports +#--------------------------------------------------------------------- +import random +import time +import logging +import ptf.packet as scapy +import socket +import ptf.dataplane as dataplane + +from ptf.testutils import * +from ptf.mask import Mask +import ipaddress + +import os +import unittest + +import ptf +from ptf.base_tests import BaseTest +from ptf import config +import ptf.dataplane as dataplane +import ptf.testutils as testutils + +import pprint + +import fib + +class DecapPacketTest(BaseTest): + def __init__(self): + ''' + @summary: constructor + ''' + BaseTest.__init__(self) + self.test_params = testutils.test_params_get() + #----------------------------------------------------------------- + def setUp(self): + ''' + @summary: Setup for the test + ''' + self.dataplane = ptf.dataplane_instance + self.router_mac = self.test_params['router_mac'] + self.fib = fib.Fib(self.test_params['fib_info']) + if self.test_params['testbed_type'] == 't1' or self.test_params['testbed_type'] == 't1-lag': + self.src_ports = range(0, 32) + if self.test_params['testbed_type'] == 't0': + self.src_ports = range(1, 25) + range(28, 32) + #----------------------------------------------------------------- + + def send_and_verify(self, dst_ip, expected_ports, src_port, triple_encap = False): + ''' + @summary: This function builds encap packet, send and verify their arrival, When a packet will not arrived as expected an exeption will be throwen + @dst_ip: the destination ip for the inner IP header + @expected_ports: list of ports that a packet can arrived from + @src_port: the physical port that the packet will be sent from + @triple_encap: Bool if to send triple encapsulated packet + ''' + #setting parameters + src_mac = self.dataplane.get_mac(0, 0) + dst_mac = '00:11:22:33:44:55' + inner_src_ip = '2.2.2.2' + router_mac = self.test_params['router_mac'] + dscp_in = random.randint(0, 32) + tos_in = dscp_in << 2 + dscp_out = random.randint(0, 32) + tos_out = dscp_out << 2 + if ("pipe" == self.test_params['dscp_mode']): + exp_tos = tos_in + elif("uniform" == self.test_params['dscp_mode']): + exp_tos = tos_out + else: + print("ERROR: no dscp is configured") + exit() + + default_packet_len = 100 + default_packet_add_header_len = 114 + + #building the packets and the expected packets + if (not triple_encap): + #for the double encap packet we will use IP header with TCP header without mac + inner_pkt = simple_ip_only_packet(ip_dst=dst_ip, ip_src=inner_src_ip, ip_ttl=64, ip_tos=tos_in) + #after the decap process the retuning packet will be normal tcp packet, The TTL is taked from the inner layer and redused by one + exp_pkt = simple_tcp_packet(pktlen=default_packet_add_header_len, + eth_dst=dst_mac, + eth_src=router_mac, + ip_dst=dst_ip, + ip_src=inner_src_ip, + ip_tos=exp_tos, + ip_ttl=63) + else: + #Building triple encap packet with SCAPY, because there is no PTF function for it, I use the defualt values for the TCP header + tcp_hdr = scapy.TCP(sport=1234, dport=80, flags="S", chksum=0) + inner_pkt2 = scapy.IP(src='4.4.4.4', dst='3.3.3.3', tos=0, ttl=64, id=1, ihl=None) / tcp_hdr + inner_pkt = scapy.IP(src=inner_src_ip, dst=dst_ip, tos=tos_in, ttl=64, id=1, ihl=None,proto=4) / inner_pkt2 + inner_pkt = inner_pkt/("".join([chr(x) for x in xrange(default_packet_len - len(inner_pkt))])) + #The expected packet is also built by scapy, and the TTL is taked from the inner layer and redused by one + exp_pkt = scapy.Ether(dst=dst_mac, src=router_mac)/inner_pkt + exp_pkt['IP'].tos = exp_tos #this parameter is taken by the decap rule configuration + exp_pkt['IP'].ttl = 63 + + pkt = simple_ipv4ip_packet( + eth_dst=router_mac, + eth_src=src_mac, + ip_src='1.1.1.1', + ip_dst=self.test_params['lo_ip'], + ip_tos=tos_out, + ip_ttl=random.randint(2, 63), + inner_frame=inner_pkt) + + #send and verify the return packets + masked_exp_pkt = Mask(exp_pkt) + masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") + masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "src") + send_packet(self, src_port, pkt) + logging.info("Sending packet from port" + str(src_port) + " to " + dst_ip + "triple_encap: " + str(triple_encap)) + (matched, received) = verify_packet_any_port(self, masked_exp_pkt, expected_ports) + assert received + return (matched, received) + #----------------------------------------------------------------- + + def runTest(self): + """ + @summary: Send double and triple encapsulated packets for each range of IPv4 and + expect the packet to be received from one of the expected ports + """ + # IPv4 Test + for ip_range in self.fib.ipv4_ranges(): + # Get the expected list of ports that would receive the packets + exp_port_list = self.fib[ip_range.get_first_ip()].get_next_hop_list() + # Choose random one source port from all ports excluding the expected ones + src_port = random.choice([port for port in self.src_ports if port not in exp_port_list]) + + if not len(exp_port_list): + continue + + # Send a packet with the first IP in the range + self.send_and_verify(ip_range.get_first_ip(), exp_port_list, src_port) + self.send_and_verify(ip_range.get_first_ip(), exp_port_list, src_port, True) + # Send a packet with the last IP in the range + if ip_range.length() > 1: + self.send_and_verify(ip_range.get_last_ip(), exp_port_list, src_port) + self.send_and_verify(ip_range.get_last_ip(), exp_port_list, src_port, True) + # Send a packet with a random IP in the range + if ip_range.length() > 2: + self.send_and_verify(ip_range.get_random_ip(), exp_port_list, src_port) + self.send_and_verify(ip_range.get_random_ip(), exp_port_list, src_port, True) +#--------------------------------------------------------------------- + + diff --git a/ansible/roles/test/files/ptftests/copp_tests.py b/ansible/roles/test/files/ptftests/copp_tests.py new file mode 100644 index 00000000000..0de3b6ee74a --- /dev/null +++ b/ansible/roles/test/files/ptftests/copp_tests.py @@ -0,0 +1,391 @@ +# ptf --test-dir saitests copp_tests --qlen=100000 --platform nn -t "verbose=True" --device-socket 0-3@tcp://127.0.0.1:10900 --device-socket 1-3@tcp://10.3.147.47:10900 +# +# copp_test.${name_test} +# +# ARPTest +# DHCPTest +# LLDPTest +# BGPTest +# LACPTest +# SNMPTest +# SSHTest +# IP2METest +# DefaultTest + +import ptf +from ptf.base_tests import BaseTest +from ptf import config +import ptf.testutils as testutils +from ptf.testutils import * +from ptf.dataplane import match_exp_pkt +import datetime +import subprocess + + +class ControlPlaneBaseTest(BaseTest): + MAX_PORTS = 32 + PPS_LIMIT = 600 + PPS_LIMIT_MIN = PPS_LIMIT * 0.9 + PPS_LIMIT_MAX = PPS_LIMIT * 1.1 + NO_POLICER_LIMIT = PPS_LIMIT * 1.4 + PKT_TX_COUNT = 100000 + PKT_RX_LIMIT = PKT_TX_COUNT * 0.90 + + def __init__(self): + BaseTest.__init__(self) + self.log_fp = open('/tmp/copp.log', 'a') + test_params = testutils.test_params_get() + self.verbose = 'verbose' in test_params and test_params['verbose'] + + self.myip = {} + self.peerip = {} + for i in xrange(self.MAX_PORTS): + self.myip[i] = "10.0.0.%d" % (i*2+1) + self.peerip[i] = "10.0.0.%d" % (i*2) + + return + + def log(self, message, debug=False): + current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + if (debug and self.verbose) or (not debug): + print "%s : %s" % (current_time, message) + self.log_fp.write("%s : %s\n" % (current_time, message)) + + def setUp(self): + self.dataplane = ptf.dataplane_instance + + self.my_mac = {} + self.peer_mac = {} + for port_id, port in self.dataplane.ports.iteritems(): + if port_id[0] == 0: + self.my_mac[port_id[1]] = port.mac() + elif port_id[0] == 1: + self.peer_mac[port_id[1]] = port.mac() + else: + assert True + + self.dataplane.flush() + if config["log_dir"] != None: + filename = os.path.join(config["log_dir"], str(self)) + ".pcap" + self.dataplane.start_pcap(filename) + + def tearDown(self): + if config["log_dir"] != None: + self.dataplane.stop_pcap() + self.log_fp.close() + + def copp_test(self, packet, count, send_intf, recv_intf): + b_c_0 = self.dataplane.get_counters(*send_intf) + b_c_1 = self.dataplane.get_counters(*recv_intf) + b_n_0 = self.dataplane.get_nn_counters(*send_intf) + b_n_1 = self.dataplane.get_nn_counters(*recv_intf) + + start_time=datetime.datetime.now() + + for i in xrange(count): + testutils.send_packet(self, send_intf, packet) + + end_time=datetime.datetime.now() + + total_rcv_pkt_cnt = testutils.count_matched_packets(self, packet, recv_intf[1], recv_intf[0]) + + e_c_0 = self.dataplane.get_counters(*send_intf) + e_c_1 = self.dataplane.get_counters(*recv_intf) + e_n_0 = self.dataplane.get_nn_counters(*send_intf) + e_n_1 = self.dataplane.get_nn_counters(*recv_intf) + self.log("", True) + self.log("Counters before the test:", True) + self.log("If counter (0, n): %s" % str(b_c_0), True) + self.log("NN counter (0, n): %s" % str(b_n_0), True) + self.log("If counter (1, n): %s" % str(b_c_1), True) + self.log("NN counter (1, n): %s" % str(b_n_1), True) + self.log("", True) + self.log("Counters after the test:", True) + self.log("If counter (0, n): %s" % str(e_c_0), True) + self.log("NN counter (0, n): %s" % str(e_n_0), True) + self.log("If counter (1, n): %s" % str(e_c_1), True) + self.log("NN counter (1, n): %s" % str(e_n_1), True) + self.log("") + self.log("Sent through NN to local ptf_nn_agent: %d" % int(e_c_0[1] - b_c_0[1])) + self.log("Sent through If to remote ptf_nn_agent: %d" % int(e_n_0[1] - b_n_0[1])) + self.log("Recv from If on remote ptf_nn_agent: %d" % int(e_c_1[0] - b_c_1[0])) + self.log("Recv from NN on from remote ptf_nn_agent: %d" % int(e_n_1[0] - b_n_1[0])) + + time_delta = end_time - start_time + time_delta_ms = (time_delta.microseconds + time_delta.seconds * 10**6) / 10**3 + tx_pps = int(count/(float(time_delta_ms)/1000)) + rx_pps = int(total_rcv_pkt_cnt/(float(time_delta_ms)/1000)) + + return total_rcv_pkt_cnt, time_delta, time_delta_ms, tx_pps, rx_pps + + def contruct_packet(self, port_number): + raise NotImplemented + + def check_constraints(self, total_rcv_pkt_cnt, time_delta_ms, rx_pps): + raise NotImplemented + + def one_port_test(self, port_number): + packet = self.contruct_packet(port_number) + total_rcv_pkt_cnt, time_delta, time_delta_ms, tx_pps, rx_pps = self.copp_test(str(packet), self.PKT_TX_COUNT, (0, port_number), (1, port_number)) + self.printStats(self.PKT_TX_COUNT, total_rcv_pkt_cnt, time_delta, tx_pps, rx_pps) + self.check_constraints(total_rcv_pkt_cnt, time_delta_ms, rx_pps) + + return + + def run_suite(self): + self.one_port_test(3) + + def printStats(self, pkt_send_count, total_rcv_pkt_cnt, time_delta, tx_pps, rx_pps): + self.log("") + self.log('test stats') + self.log('Packet sent = %10d' % pkt_send_count) + self.log('Packet rcvd = %10d' % total_rcv_pkt_cnt) + self.log('Test time = %s' % str(time_delta)) + self.log('TX PPS = %d' % tx_pps) + self.log('RX PPS = %d' % rx_pps) + + return + +class NoPolicyTest(ControlPlaneBaseTest): + def __init__(self): + ControlPlaneBaseTest.__init__(self) + + def check_constraints(self, total_rcv_pkt_cnt, time_delta_ms, rx_pps): + self.log("") + self.log("Checking constraints (NoPolicy):") + self.log("rx_pps (%d) > NO_POLICER_LIMIT (%d): %s" % (int(rx_pps), int(self.NO_POLICER_LIMIT), str(rx_pps > self.NO_POLICER_LIMIT))) + self.log("total_rcv_pkt_cnt (%d) > PKT_RX_LIMIT (%d): %s" % \ + (int(total_rcv_pkt_cnt), int(self.PKT_RX_LIMIT), str(total_rcv_pkt_cnt > self.PKT_RX_LIMIT))) + + assert(rx_pps > self.NO_POLICER_LIMIT) + assert(total_rcv_pkt_cnt > self.PKT_RX_LIMIT) + +class PolicyTest(ControlPlaneBaseTest): + def __init__(self): + ControlPlaneBaseTest.__init__(self) + + def check_constraints(self, total_rcv_pkt_cnt, time_delta_ms, rx_pps): + self.log("") + self.log("Checking constraints (PolicyApplied):") + self.log("PPS_LIMIT_MIN (%d) <= rx_pps (%d) <= PPS_LIMIT_MAX (%d): %s" % \ + (int(self.PPS_LIMIT_MIN), int(rx_pps), int(self.PPS_LIMIT_MAX), str(self.PPS_LIMIT_MIN <= rx_pps <= self.PPS_LIMIT_MAX))) + + assert(self.PPS_LIMIT_MIN <= rx_pps <= self.PPS_LIMIT_MAX) + + +# SONIC config contains policer CIR=600 for ARP +class ARPTest(PolicyTest): + def __init__(self): + PolicyTest.__init__(self) + + def runTest(self): + self.log("ARPTest") + self.run_suite() + + def contruct_packet(self, port_number): + src_mac = self.my_mac[port_number] + src_ip = self.myip[port_number] + dst_ip = self.peerip[port_number] + + packet = simple_arp_packet( + eth_dst='ff:ff:ff:ff:ff:ff', + eth_src=src_mac, + arp_op=1, + ip_snd=src_ip, + ip_tgt=dst_ip, + hw_snd=src_mac, + hw_tgt='ff:ff:ff:ff:ff:ff') + + return packet + +# SONIC configuration has no policer limiting for DHCP +class DHCPTest(NoPolicyTest): + def __init__(self): + NoPolicyTest.__init__(self) + + def runTest(self): + self.log("DHCPTest") + self.run_suite() + + def contruct_packet(self, port_number): + src_mac = self.my_mac[port_number] + packet = simple_udp_packet(pktlen=100, + eth_dst='ff:ff:ff:ff:ff:ff', + eth_src=src_mac, + dl_vlan_enable=False, + vlan_vid=0, + vlan_pcp=0, + dl_vlan_cfi=0, + ip_src='0.0.0.0', + ip_dst='255.255.255.255', + ip_tos=0, + ip_ttl=64, + udp_sport=68, + udp_dport=67, + ip_ihl=None, + ip_options=False, + with_udp_chksum=True + ) + + return packet + + +# SONIC configuration has no policer limiting for LLDP +class LLDPTest(NoPolicyTest): + def __init__(self): + NoPolicyTest.__init__(self) + + def runTest(self): + self.log("LLDPTest") + self.run_suite() + + def contruct_packet(self, port_number): + src_mac = self.my_mac[port_number] + packet = simple_eth_packet( + eth_dst='01:80:c2:00:00:0e', + eth_src=src_mac, + eth_type=0x88cc + ) + + return packet + +# SONIC configuration has no policer limiting for BGP +class BGPTest(NoPolicyTest): + def __init__(self): + NoPolicyTest.__init__(self) + + def runTest(self): + self.log("BGPTest") + self.run_suite() + + def contruct_packet(self, port_number): + dst_mac = self.peer_mac[port_number] + dst_ip = self.peerip[port_number] + packet = simple_tcp_packet( + eth_dst=dst_mac, + ip_dst=dst_ip, + tcp_dport=179 + ) + return packet + +# SONIC configuration has no policer limiting for LACP +class LACPTest(NoPolicyTest): + def __init__(self): + NoPolicyTest.__init__(self) + + def runTest(self): + self.log("LACPTest") + self.run_suite() + + def contruct_packet(self, port_number): + packet = simple_eth_packet( + pktlen=14, + eth_dst='01:80:c2:00:00:02', + eth_type=0x8809 + ) / (chr(0x01)+(chr(0x01))) + + return packet + +# SNMP packets are trapped as IP2ME packets. +# IP2ME configuration in SONIC contains policer CIR=600 +class SNMPTest(PolicyTest): #FIXME: trapped as ip2me. mellanox should add support for SNMP trap + def __init__(self): + PolicyTest.__init__(self) + + def runTest(self): + self.log("SNMPTest") + self.run_suite() + + def contruct_packet(self, port_number): + src_mac = self.my_mac[port_number] + dst_mac = self.peer_mac[port_number] + dst_ip = self.peerip[port_number] + packet = simple_udp_packet( + eth_dst=dst_mac, + ip_dst=dst_ip, + eth_src=src_mac, + udp_dport=161 + ) + return packet + +# SONIC configuration has no policer limiting for SSH +class SSHTest(PolicyTest): # FIXME: ssh is policed now + def __init__(self): + PolicyTest.__init__(self) + + def runTest(self): + self.log("SSHTest") + self.run_suite() + + def contruct_packet(self, port_number): + dst_mac = self.peer_mac[port_number] + src_ip = self.myip[port_number] + dst_ip = self.peerip[port_number] + + packet = simple_tcp_packet( + eth_dst=dst_mac, + ip_dst=dst_ip, + ip_src=src_ip, + tcp_flags='F', + tcp_sport=22, + tcp_dport=22) + + return packet + +# IP2ME configuration in SONIC contains policer CIR=600 +class IP2METest(PolicyTest): + def __init__(self): + PolicyTest.__init__(self) + + def runTest(self): + self.log("IP2METest") + self.run_suite() + + def one_port_test(self, port_number): + for port in self.dataplane.ports.iterkeys(): + if port[0] == 0: + continue + packet = self.contruct_packet(port[1]) + total_rcv_pkt_cnt, time_delta, time_delta_ms, tx_pps, rx_pps = self.copp_test(str(packet), self.PKT_TX_COUNT, (0, port_number), (1, port_number)) + self.printStats(self.PKT_TX_COUNT, total_rcv_pkt_cnt, time_delta, tx_pps, rx_pps) + self.check_constraints(total_rcv_pkt_cnt, time_delta_ms, rx_pps) + + return + + def contruct_packet(self, port_number): + src_mac = self.my_mac[port_number] + dst_mac = self.peer_mac[port_number] + dst_ip = self.peerip[port_number] + + packet = simple_tcp_packet( + eth_src=src_mac, + eth_dst=dst_mac, + ip_dst=dst_ip + ) + + return packet + + +class DefaultTest(PolicyTest): + def __init__(self): + PolicyTest.__init__(self) + + def runTest(self): + self.log("DefaultTest") + self.run_suite() + + def contruct_packet(self, port_number): + dst_mac = self.peer_mac[port_number] + src_ip = self.myip[port_number] + dst_port_number = (port_number + 1) % self.MAX_PORTS + dst_ip = self.peerip[dst_port_number] + + packet = simple_tcp_packet( + eth_dst=dst_mac, + ip_dst=dst_ip, + ip_src=src_ip, + tcp_sport=10000, + tcp_dport=10000, + ip_ttl=1) + + return packet diff --git a/ansible/roles/test/files/ptftests/ecmp_test.py b/ansible/roles/test/files/ptftests/ecmp_test.py new file mode 100644 index 00000000000..fac78b7fbad --- /dev/null +++ b/ansible/roles/test/files/ptftests/ecmp_test.py @@ -0,0 +1,159 @@ +""" +SONiC Dataplane ECMP tests +""" +import random +import time +import logging +import ptf.packet as scapy +import socket +import datetime +import ptf.dataplane as dataplane +import ptf.testutils as testutils +import ptf +from ptf import config +from ptf.testutils import * +from ptf.mask import Mask +from ptf.base_tests import BaseTest + +# For SONiC +# testing ECMP uniformn distribution over 16 RIFs from 16 differnt ports +# ---- Test require 32 connected ports and SONiC up and running ---- +# ---- MUST RUN WITH "--relax" option on the ptf running line ---- +# Preliminary steps +# 1. Configure IPs of all of the connected ports +# (SONiC will configure neighbors) +# 2. configure all routes (run add_routes.sh on SONiC) + +# Test structure +# Sending Packets sequance +# 1. Main loop running on 16 sources ports +# 2. IP_LAST_WORD_RANGE loop running from 0-254 +# 3. IP_2ND_LAST_WORD_RANGE loop running 0-15 +# 4. Inside loop, to increase the number of packets, with differnt ports +# 5. Sending and reciving packets, and counting destanation ports +# - Final counters checking for uniform distribution + +# Final steps +# For cleaning configuration run remove_routes.sh from SONiC + + +# Constants +IP_LAST_WORD_RANGE = 254 +IP_2ND_LAST_WORD_RANGE = 16 +NUMBER_OF_SRC_PORTS = 16 +NUMBER_OF_DST_PORTS = 16 + + +class ECMPtest(BaseTest): + def __init__(self): + BaseTest.__init__(self) + self.test_params = testutils.test_params_get() + self.verbose = self.test_params['verbose'] + self.log_fp = open('/tmp/ecmp.log', 'a') + + def log(self, message, debug=False): + current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + if (debug and self.verbose) or (not debug): + print "%s : %s" % (current_time, message) + self.log_fp.write("%s : %s\n" % (current_time, message)) + + def runTest(self): + self.pkt_counter = [0]*NUMBER_OF_DST_PORTS + self.send_packets() + self.check_distribution() + + def send_packets(self): + random.seed(time.time()) + sport = 0x1234 + dport = 0x50 + router_mac = self.test_params['router_mac'] + destanation_ports = range(NUMBER_OF_SRC_PORTS,NUMBER_OF_DST_PORTS+NUMBER_OF_SRC_PORTS) + self.log("the router mac is %s" % router_mac) + self.log("the rif macs are:") + for i in range(16): + self.log(" %s" % self.dataplane.get_mac(0, i+16)) + + #send packets + for port in xrange(NUMBER_OF_SRC_PORTS): + for i in xrange(IP_LAST_WORD_RANGE): + for j in xrange(IP_2ND_LAST_WORD_RANGE): + ip_src = '10.0.0.' + str(port * 2 + 32) + src_mac = self.dataplane.get_mac(0, 0) + ip_dst = '172.16.' + str(j) + '.' + str(i + 1) + + pkt = simple_tcp_packet( + eth_dst=router_mac, + eth_src=src_mac, + ip_src=ip_src, + ip_dst=ip_dst, + ip_id=i*j*port, + tcp_sport=sport, + tcp_dport=dport, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst=self.dataplane.get_mac(0, 16), + eth_src=router_mac, + ip_src=ip_src, + ip_dst=ip_dst, + ip_id=i*j*port, + tcp_sport=sport, + tcp_dport=dport, + ip_ttl=63) + masked_exp_pkt = Mask(exp_pkt) + masked_exp_pkt.set_do_not_care_scapy(scapy.Ether,"dst") + + sleep_time = 1 + repeat = 5 # Repeat the send action until we receive a packet + while True: + send_packet(self, port, pkt) + self.log("Sent packet src=%s dst=%s port=%s" % (ip_src, ip_dst, port), True) + port_index = self.verify_packet_any_port(masked_exp_pkt, destanation_ports) + if port_index is None: + self.log("Expected packet isn't received. Repeating", True) + time.sleep(sleep_time) + sleep_time *= 2 + repeat -= 1 + if repeat == 0: + self.fail("Can't receive packet: src=%s dst=%s port=%s" % (ip_src, ip_dst, port)) + else: + break + self.log("Received expected packet from port %d" % destanation_ports[port_index], True) + + self.pkt_counter[port_index] += 1 + sport = random.randint(0,0xffff) + dport = random.randint(0,0xffff) + return + + def check_distribution(self): + #final uniform distribution check + + self.log("") + for i, counter in enumerate(self.pkt_counter): + self.log("Port %02d counter: %d" % (i, counter)) + + for stat_port in xrange(NUMBER_OF_DST_PORTS): + self.assertTrue((self.pkt_counter[stat_port] >= ((IP_LAST_WORD_RANGE * IP_2ND_LAST_WORD_RANGE) * 0.9)), + "Not all paths are equally balanced, %s" % self.pkt_counter[stat_port]) + self.assertTrue((self.pkt_counter[stat_port] <= ((IP_LAST_WORD_RANGE * IP_2ND_LAST_WORD_RANGE) * 1.1)), + "Not all paths are equally balanced, %s" % self.pkt_counter[stat_port]) + + return + + def setUp(self): + BaseTest.setUp(self) + self.dataplane = ptf.dataplane_instance + self.dataplane.flush() + + def tearDown(self): + if config["log_dir"] != None: + self.dataplane.stop_pcap() + self.log_fp.close() + BaseTest.tearDown(self) + + def verify_packet_any_port(self, pkt, ports=[], device_number=0): + (rcv_device, rcv_port, rcv_pkt, pkt_time) = dp_poll(self, device_number=device_number, exp_pkt=pkt, timeout=1) + + if rcv_port in ports: + return ports.index(rcv_port) + else: + return None diff --git a/ansible/roles/test/files/ptftests/fast-reboot.py b/ansible/roles/test/files/ptftests/fast-reboot.py index b0007b00a83..f3c3d0c741d 100644 --- a/ansible/roles/test/files/ptftests/fast-reboot.py +++ b/ansible/roles/test/files/ptftests/fast-reboot.py @@ -1,5 +1,5 @@ # -#ptf --test-dir ptftests fast-reboot.FastReloadTest --platform remote --platform-dir ptftests --qlen 1000 -t "verbose=True;dut_username='acsadmin';dut_hostname='10.251.0.243';fast_reboot_limit=30;portchannel_ports_file='/tmp/portchannel_interfaces.json';vlan_ports_file='/tmp/vlan_interfaces.json';port_indices_file='/tmp/port_indices.json';dut_mac='4c:76:25:f4:b7:00';vlan_ip_range='172.0.0.0/26';default_ip_range='192.168.0.0/16'" +#ptf --test-dir ptftests fast-reboot.FastReloadTest --platform remote --platform-dir ptftests --qlen 1000 -t "verbose=True;dut_username='acsadmin';dut_hostname='10.3.147.243';fast_reboot_limit=30;portchannel_ports_file='/tmp/portchannel_interfaces.json';vlan_ports_file='/tmp/vlan_interfaces.json';ports_file='/tmp/ports.json';dut_mac='4c:76:25:f4:b7:00';vlan_ip_range='172.0.0.0/26';default_ip_range='192.168.0.0/16';vlan_ip_range='172.0.0.0/26'" # # # This test measures length of DUT dataplane disruption in fast-reboot procedure. @@ -33,8 +33,12 @@ import struct import socket from pprint import pprint +from fcntl import ioctl import sys import json +import re +from collections import defaultdict +import json class FastReloadTest(BaseTest): def __init__(self): @@ -47,51 +51,19 @@ def __init__(self): self.check_param('fast_reboot_limit', 30, required = False) self.check_param('portchannel_ports_file', '', required = True) self.check_param('vlan_ports_file', '', required = True) - self.check_param('port_indices_file', '', required = True) + self.check_param('ports_file', '', required = True) self.check_param('dut_mac', '', required = True) self.check_param('default_ip_range', '', required = True) + self.check_param('vlan_ip_range', '', required = True) # Default settings - self.nr_pkts = 100 + self.nr_pc_pkts = 100 self.nr_tests = 3 self.reboot_delay = 10 self.task_timeout = 300 # Wait up to 5 minutes for tasks to complete + self.max_nr_vl_pkts = 1000 self.timeout_thr = None - self.read_port_indices() - portchannel_ports = self.read_portchannel_ports() - vlan_ip_range = self.read_vlan_ip_range() - vlan_ports = self.read_vlan_ports() - - self.limit = datetime.timedelta(seconds=self.test_params['fast_reboot_limit']) - self.dut_ssh = self.test_params['dut_username'] + '@' + self.test_params['dut_hostname'] - self.dut_mac = self.test_params['dut_mac'] - # - self.from_t1_src_addr = self.random_ip(self.test_params['default_ip_range']) - self.from_t1_src_port = self.random_port(portchannel_ports) - self.from_t1_dst_addr = self.random_ip(vlan_ip_range) - self.from_t1_dst_ports = [self.random_port(vlan_ports)] - self.from_t1_if_name = "eth%d" % self.from_t1_dst_ports[0] - self.from_t1_if_addr = "%s/%s" % (self.from_t1_dst_addr, vlan_ip_range.split('/')[1]) - # - self.from_server_src_addr = self.random_ip(vlan_ip_range) - self.from_server_src_port = self.random_port(vlan_ports) - self.from_server_dst_addr = self.random_ip(self.test_params['default_ip_range']) - self.from_server_dst_ports = portchannel_ports - - self.log("Test params:") - self.log("DUT ssh: %s" % self.dut_ssh) - self.log("DUT fast-reboot limit: %s" % self.limit) - self.log("DUT mac address: %s" % self.dut_mac) - self.log("From T1 src addr: %s" % self.from_t1_src_addr) - self.log("From T1 src port: %s" % self.from_t1_src_port) - self.log("From T1 dst addr: %s" % self.from_t1_dst_addr) - self.log("From T1 dst ports: %s" % self.from_t1_dst_ports) - self.log("From server src addr: %s" % self.from_server_src_addr) - self.log("From server src port: %s" % self.from_server_src_port) - self.log("From server dst addr: %s" % self.from_server_dst_addr) - self.log("From server dst ports: %s" % self.from_server_dst_ports) - return def read_json(self, name): @@ -101,26 +73,23 @@ def read_json(self, name): return content def read_port_indices(self): - self.port_indices = self.read_json('port_indices_file') + self.port_indices = self.read_json('ports_file') + + return def read_portchannel_ports(self): content = self.read_json('portchannel_ports_file') pc_ifaces = [] - for pc in content: + for pc in content.values(): pc_ifaces.extend([self.port_indices[member] for member in pc['members']]) return pc_ifaces - def read_vlan_ip_range(self): - content = self.read_json('vlan_ports_file') - if len(content) > 1: - self.log('DUT has more than 1 VLANS') - return content[0]['subnet'] - def read_vlan_ports(self): content = self.read_json('vlan_ports_file') - - return [self.port_indices[ifname] for ifname in content[0]['members'].split(" ")] + if len(content) > 1: + raise "Too many vlans" + return [self.port_indices[ifname] for ifname in content.values()[0]['members']] def check_param(self, param, default, required = False): if param not in self.test_params: @@ -129,15 +98,22 @@ def check_param(self, param, default, required = False): self.test_params[param] = default def random_ip(self, ip): - src_addr, mask = ip.split('/') + net_addr, mask = ip.split('/') n_hosts = 2**(32 - int(mask)) random_host = random.randint(2, n_hosts - 2) + return self.host_ip(ip, random_host) + + def host_ip(self, net_ip, host_number): + src_addr, mask = net_ip.split('/') + n_hosts = 2**(32 - int(mask)) + if host_number > (n_hosts - 2): + raise Exception("host number %d is greater than number of hosts %d in the network %s" % (host_number, n_hosts - 2, net_ip)) src_addr_n = struct.unpack(">I", socket.inet_aton(src_addr))[0] net_addr_n = src_addr_n & (2**32 - n_hosts) - random_addr_n = net_addr_n + random_host - random_ip = socket.inet_ntoa(struct.pack(">I", random_addr_n)) + host_addr_n = net_addr_n + host_number + host_ip = socket.inet_ntoa(struct.pack(">I", host_addr_n)) - return random_ip + return host_ip def random_port(self, ports): return random.choice(ports) @@ -166,10 +142,33 @@ def cancel_timeout(self): self.timeout_thr = None def setUp(self): - print + self.read_port_indices() + self.portchannel_ports = self.read_portchannel_ports() + vlan_ip_range = self.test_params['vlan_ip_range'] + self.vlan_ports = self.read_vlan_ports() + + self.limit = datetime.timedelta(seconds=self.test_params['fast_reboot_limit']) + self.dut_ssh = self.test_params['dut_username'] + '@' + self.test_params['dut_hostname'] + self.dut_mac = self.test_params['dut_mac'] + # + self.from_server_src_addr = self.random_ip(vlan_ip_range) + self.from_server_src_port = self.random_port(self.vlan_ports) + self.from_server_dst_addr = self.random_ip(self.test_params['default_ip_range']) + self.from_server_dst_ports = self.portchannel_ports + + self.nr_vl_pkts = self.generate_from_t1() + + self.log("Test params:") + self.log("DUT ssh: %s" % self.dut_ssh) + self.log("DUT fast-reboot limit: %s" % self.limit) + self.log("DUT mac address: %s" % self.dut_mac) + + self.log("From server src addr: %s" % self.from_server_src_addr) + self.log("From server src port: %s" % self.from_server_src_port) + self.log("From server dst addr: %s" % self.from_server_dst_addr) + self.log("From server dst ports: %s" % self.from_server_dst_ports) + self.log("From upper layer number of packets: %d" % self.nr_vl_pkts) - self.cmd(['ifconfig', self.from_t1_if_name, self.from_t1_if_addr]) - # FIXME: Check return value for self.cmd self.dataplane = ptf.dataplane_instance for p in self.dataplane.ports.values(): port = p.get_packet_source() @@ -180,19 +179,84 @@ def setUp(self): filename = os.path.join(config["log_dir"], str(self)) + ".pcap" self.dataplane.start_pcap(filename) + self.log("Enabling arp_responder") + self.cmd(["supervisorctl", "start", "arp_responder"]) + + return + def tearDown(self): - self.cmd(['ifconfig', self.from_t1_if_name, '0']) - # FIXME: Check return value for self.cmd + self.log("Disabling arp_responder") + self.cmd(["supervisorctl", "stop", "arp_responder"]) if config["log_dir"] != None: self.dataplane.stop_pcap() self.log_fp.close() + def get_if(self, iff, cmd): + s = socket.socket() + ifreq = ioctl(s, cmd, struct.pack("16s16x",iff)) + s.close() + + return ifreq + + def get_mac(self, iff): + SIOCGIFHWADDR = 0x8927 # Get hardware address + return ':'.join(['%02x' % ord(char) for char in self.get_if(iff, SIOCGIFHWADDR)[18:24]]) + + def generate_from_t1(self): + self.from_t1 = [] + self.ip_addr = [] + + vlan_ip_range = self.test_params['vlan_ip_range'] + + _, mask = vlan_ip_range.split('/') + n_hosts = min(2**(32 - int(mask)) - 3, self.max_nr_vl_pkts) + + for i in xrange(2, n_hosts + 2): + from_t1_src_addr = self.random_ip(self.test_params['default_ip_range']) + from_t1_src_port = self.random_port(self.portchannel_ports) + from_t1_dst_addr = self.host_ip(vlan_ip_range, i) + from_t1_dst_ports = self.vlan_ports[i % len(self.vlan_ports)] + from_t1_if_name = "eth%d" % from_t1_dst_ports + from_t1_if_addr = "%s/%s" % (from_t1_dst_addr, vlan_ip_range.split('/')[1]) + packet = simple_tcp_packet( + eth_dst=self.dut_mac, + ip_src=from_t1_src_addr, + ip_dst=from_t1_dst_addr, + ip_ttl=255, + tcp_dport=5000 + ) + self.from_t1.append((from_t1_src_port, from_t1_dst_ports, str(packet))) + self.ip_addr.append((from_t1_if_name, from_t1_if_addr)) + + exp_packet = simple_tcp_packet( + ip_src="0.0.0.0", + ip_dst="0.0.0.0", + tcp_dport=5000, + ) + + self.from_t1_exp_packet = Mask(exp_packet) + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.Ether, "src") + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.Ether, "dst") + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "src") + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "dst") + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "chksum") + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.TCP, "chksum") + self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "ttl") + + # save data for arp_replay process + with open("/tmp/from_t1.json", "w") as fp: + d = defaultdict(list) + for e in self.ip_addr: + d[e[0]].append(e[1].split('/')[0]) + json.dump(d, fp) + + return n_hosts + def runTest(self): no_routing_start = None no_routing_stop = None thr = threading.Thread(target=self.background) thr.setDaemon(True) - self.log("Check that device is alive and pinging") self.assertTrue(self.check_alive(), 'DUT is not stable') @@ -207,7 +271,7 @@ def runTest(self): self.log("ASIC was stopped, Waiting until it's up. Stop time: %s" % str(no_routing_start)) self.timeout(self.task_timeout, "DUT hasn't started to work for %d seconds" % self.task_timeout) no_routing_stop = self.check_start() - self.cancel_timeout() + self.cancel_timeout() self.log("ASIC works again. Start time: %s" % str(no_routing_stop)) self.log("Downtime was %s" % str(no_routing_stop - no_routing_start)) @@ -280,44 +344,27 @@ def check_alive(self): else: if was_alive > 0: return False # Stopped working after it working for sometime? - time.sleep(1) return was_alive > self.nr_tests def ping_alive(self): nr_from_s = self.pingFromServers() nr_from_l = self.pingFromUpperTier() - is_success_from_s = nr_from_s > self.nr_pkts * 0.7 - is_success_from_l = nr_from_l > self.nr_pkts * 0.7 + is_success_from_s = nr_from_s > self.nr_pc_pkts * 0.7 + is_success_from_l = nr_from_l > self.nr_vl_pkts * 0.7 return is_success_from_s and is_success_from_l def pingFromServers(self): - return self.ping0(self.dut_mac, - self.from_server_src_addr, - self.from_server_dst_addr, - self.from_server_src_port, - self.from_server_dst_ports, - "servers->t1") - - def pingFromUpperTier(self): - return self.ping0(self.dut_mac, - self.from_t1_src_addr, - self.from_t1_dst_addr, - self.from_t1_src_port, - self.from_t1_dst_ports, - "t1->servers") - - def ping0(self, eth_dst, ip_src, ip_dst, from_port, to_ports, msg): packet = simple_tcp_packet( - eth_dst=eth_dst, - ip_src=ip_src, - ip_dst=ip_dst, + eth_dst=self.dut_mac, + ip_src=self.from_server_src_addr, + ip_dst=self.from_server_dst_addr, tcp_dport=5000 ) exp_packet = simple_tcp_packet( - ip_src=ip_src, - ip_dst=ip_dst, + ip_src=self.from_server_src_addr, + ip_dst=self.from_server_dst_addr, ip_ttl=63, tcp_dport=5000, ) @@ -326,12 +373,23 @@ def ping0(self, eth_dst, ip_src, ip_dst, from_port, to_ports, msg): exp_packet.set_do_not_care_scapy(scapy.Ether,"src") exp_packet.set_do_not_care_scapy(scapy.Ether,"dst") - for i in xrange(self.nr_pkts): - testutils.send_packet(self, from_port, str(packet)) + raw_packet = str(packet) - total_rcv_pkt_cnt = testutils.count_matched_packets_all_ports(self, exp_packet, to_ports) + for i in xrange(self.nr_pc_pkts): + testutils.send_packet(self, self.from_server_src_port, raw_packet) - self.log("Send %5d Received %5d %s" % (self.nr_pkts, total_rcv_pkt_cnt, msg), True) + total_rcv_pkt_cnt = testutils.count_matched_packets_all_ports(self, exp_packet, self.from_server_dst_ports) + + self.log("Send %5d Received %5d servers->t1" % (self.nr_pc_pkts, total_rcv_pkt_cnt), True) return total_rcv_pkt_cnt + def pingFromUpperTier(self): + for entry in self.from_t1: + testutils.send_packet(self, entry[0], entry[2]) + + total_rcv_pkt_cnt = testutils.count_matched_packets_all_ports(self, self.from_t1_exp_packet, self.vlan_ports) + + self.log("Send %5d Received %5d t1->servers" % (self.nr_vl_pkts, total_rcv_pkt_cnt), True) + + return total_rcv_pkt_cnt diff --git a/ansible/roles/test/files/ptftests/fib.py b/ansible/roles/test/files/ptftests/fib.py new file mode 100644 index 00000000000..d4dc005f9e5 --- /dev/null +++ b/ansible/roles/test/files/ptftests/fib.py @@ -0,0 +1,76 @@ +import re +from ipaddress import ip_address, ip_network +from lpm import LpmDict + +# These subnets are excluded from FIB test +# reference: RFC 5735 Special Use IPv4 Addresses +# RFC 5156 Special Use IPv6 Addresses + +EXCLUDE_IPV4_PREFIXES = [ + '0.0.0.0/8', # "This" Network RFC 1122, Section 3.2.1.3 + '10.0.0.0/8', # Private-Use Networks RFC 1918 + '127.0.0.0/8', # Loopback RFC 1122, Section 3.2.1.3 + '169.254.0.0/16', # Link Local RFC RFC 3927 + '224.0.0.0/4', # Multicast RFC 3171 + '255.255.255.255/32' # Limited Broadcast RFC 919, Section 7 + # RFC 922, Section 7 +] + +EXCLUDE_IPV6_PREFIXES = [ + '::/0', # Currently no IPv6 default route + '::/128', # Unspecified RFC 4291 + '::1/128', # Loopback RFC 4291 + 'ff00::/8' # Multicast RFC 4291 + ] + +class Fib(): + class NextHop(): + def __init__(self, next_hop = ''): + self._next_hop = [] + matches = re.findall('\[([\s\d]+)\]', next_hop) + for match in matches: + self._next_hop.append([int(s) for s in match.split()]) + + def __str__(self): + return str(self._next_hop) + + def get_next_hop(self): + return self._next_hop + + def get_next_hop_list(self): + port_list = [p for intf in self._next_hop for p in intf] + return port_list + + # Initialize FIB with FIB file + def __init__(self, file_path): + self._ipv4_lpm_dict = LpmDict() + for ip in EXCLUDE_IPV4_PREFIXES: + self._ipv4_lpm_dict[ip] = self.NextHop() + + self._ipv6_lpm_dict = LpmDict(ipv4=False) + for ip in EXCLUDE_IPV6_PREFIXES: + self._ipv6_lpm_dict[ip] = self.NextHop() + + with open(file_path, 'r') as f: + for line in f.readlines(): + if line[0] == '#': continue + entry = line.split(' ', 1) + prefix = ip_network(unicode(entry[0])) + next_hop = self.NextHop(entry[1]) + if prefix.version is 4: + self._ipv4_lpm_dict[str(prefix)] = next_hop + elif prefix.version is 6: + self._ipv6_lpm_dict[str(prefix)] = next_hop + + def __getitem__(self, ip): + ip = ip_address(unicode(ip)) + if ip.version is 4: + return self._ipv4_lpm_dict[str(ip)] + elif ip.version is 6: + return self._ipv6_lpm_dict[str(ip)] + + def ipv4_ranges(self): + return self._ipv4_lpm_dict.ranges() + + def ipv6_ranges(self): + return self._ipv6_lpm_dict.ranges() diff --git a/ansible/roles/test/files/ptftests/fib_test.py b/ansible/roles/test/files/ptftests/fib_test.py index 6cccc87240d..dcec770d9e4 100644 --- a/ansible/roles/test/files/ptftests/fib_test.py +++ b/ansible/roles/test/files/ptftests/fib_test.py @@ -25,6 +25,8 @@ from ptf.mask import Mask from ptf.testutils import * +import fib + class FibTest(BaseTest): ''' @summary: Overview of functionality @@ -56,15 +58,9 @@ class FibTest(BaseTest): #--------------------------------------------------------------------- # Class variables #--------------------------------------------------------------------- - EXPECTED_RANGE = 0.25 # TODO: need to get the percentage from param - - ''' - Information about routes to test. - ''' - source_port_list = [] # a list of source port indices - dest_port_list = [] # a list of lists describing ecmp/lag relationships - route_list = [] # a list of route to be tested - hit_dict = {} # a dict of hit count recording the number of hits per port + DEFAULT_BALANCING_RANGE = 0.25 + BALANCING_TEST_TIMES = 5000 + DEFAULT_BALANCING_TEST_RATIO = 0.0001 def __init__(self): ''' @@ -72,112 +68,89 @@ def __init__(self): ''' BaseTest.__init__(self) self.test_params = test_params_get() + #--------------------------------------------------------------------- def setUp(self): ''' @summary: Setup for the test + Two test parameters are used: + - fib_info: the FIB information generated according to the testbed + - router_mac: the MAC address of the DUT used to create the eth_dst + of the packet + - testbed_type: the type of the testbed used to determine the source + port + TODO: Have a separate line in fib_info/file to indicate all UP ports ''' self.dataplane = ptf.dataplane_instance - self.testbed = self.test_params['testbed_type'] + self.fib = fib.Fib(self.test_params['fib_info']) self.router_mac = self.test_params['router_mac'] - self.load_route_info(self.test_params["route_info"]) - - if self.testbed == 't0': - self.source_port_list = range(1,25) + range(28,32) - self.dest_port_list = [[i] for i in range(28,32)] - elif self.testbed == 't1': - self.source_port_list = range(16,32) - self.dest_port_list = [[i] for i in range(0,16)] - elif self.testbed == 't1-lag': - self.source_port_list = range(16,32) - self.dest_port_list = [[i, i+1] for i in range(0,16,2)] - #--------------------------------------------------------------------- - def load_route_info(self, route_info_path): - ''' - @summary: Load route_info file - @param route_info_path : Path to the file - ''' - with open(route_info_path, 'r') as route_info_file: - content = route_info_file.readlines() - for line in content: - self.route_list.append(line.strip()) - return - #--------------------------------------------------------------------- + self.test_ipv4 = self.test_params.get('ipv4', True) + self.test_ipv6 = self.test_params.get('ipv6', True) - def verify_packet_any_port(self, pkt, ports=[], device_number=0): - """ - @summary: Check that the packet is received on _any_ of the specified ports belonging to - the given device (default device_number is 0). + self.balancing_range = self.test_params.get('balancing_range', self.DEFAULT_BALANCING_RANGE) + self.balancing_test_ratio = self.test_params.get('balancing_test_ratio', self.DEFAULT_BALANCING_TEST_RATIO) - The function returns when either the expected packet is received or timeout (1 second). + if self.test_params['testbed_type'] == 't1' or self.test_params['testbed_type'] == 't1-lag': + self.src_ports = range(0, 32) + if self.test_params['testbed_type'] == 't0': + self.src_ports = range(1, 25) + range(28, 32) + #--------------------------------------------------------------------- - Also verifies that the packet is or received on any other ports for this - device, and that no other packets are received on the device (unless --relax - is in effect). - @param pkt : packet to verify - @param ports : list of ports + def check_ip_range(self, ipv4=True): + if ipv4: + ip_ranges = self.fib.ipv4_ranges() + else: + ip_ranges = self.fib.ipv6_ranges() - @return: index of the port on which the packet is received and the packet. - """ - received = False - match_index = -1 - (rcv_device, rcv_port, rcv_pkt, pkt_time) = dp_poll( - self, - device_number=device_number, - exp_pkt=pkt, - timeout=1 - ) - - if rcv_port in ports: - match_index = ports.index(rcv_port) - received = True - - return (match_index, received) - #--------------------------------------------------------------------- + for ip_range in ip_ranges: + # Get the expected list of ports that would receive the packets + exp_port_list = self.fib[ip_range.get_first_ip()].get_next_hop_list() + # Choose random one source port from all ports excluding the expected ones + src_port = random.choice([port for port in self.src_ports if port not in exp_port_list]) - def is_ipv4_address(self, ipaddr): - ''' - @summary: Check address is valid IPv4 address. - @param ipaddr IP address to check - @return Boolean - ''' - try: - # building ipaddress fails for some of addresses unless unicode(ipaddr) is specified for both ipv4/ipv6 - # Example - 192.168.156.129, it is valid IPV4 address, send_packet works with it. - ipaddress.IPv4Address(unicode(ipaddr)) - return True - except Exception, e: - return False - #--------------------------------------------------------------------- + if not len(exp_port_list): + continue - def is_ipv6_address(self, ipaddr): - ''' - @summary: Check address is valid IPv6 address. - @param ipaddr IP address to check - @return Boolean - ''' - try: - ipaddress.IPv6Address(unicode(ipaddr)) - return True - except Exception, e: - return False - #--------------------------------------------------------------------- + # Send a packet with the first IP in the range + self.check_ip_route(src_port, ip_range.get_first_ip(), exp_port_list, ipv4) + # Send a packet with the last IP in the range + if ip_range.length() > 1: + self.check_ip_route(src_port, ip_range.get_last_ip(), exp_port_list, ipv4) + # Send a packet with a random IP in the range + if ip_range.length() > 2: + self.check_ip_route(src_port, ip_range.get_random_ip(), exp_port_list, ipv4) + + # Test traffic balancing across ECMP/LAG members + if len(exp_port_list) > 1 and random.random() < self.balancing_test_ratio: + dst_ip = ip_range.get_random_ip() + hit_count_map = {} + for i in range(0, self.BALANCING_TEST_TIMES): + (matched_index, received) = self.check_ip_route(src_port, dst_ip, exp_port_list, ipv4) + hit_count_map[matched_index] = hit_count_map.get(matched_index, 0) + 1 + self.check_balancing(self.fib[dst_ip].get_next_hop(), hit_count_map) + + def check_ip_route(self, src_port, dst_ip_addr, dst_port_list, ipv4=True): + if ipv4: + (matched_index, received) = self.check_ipv4_route(src_port, dst_ip_addr, dst_port_list) + else: + (matched_index, received) = self.check_ipv6_route(src_port, dst_ip_addr, dst_port_list) - def check_ipv4_route(self, source_port_index, dest_ip_addr, destination_port_list): + assert received + return (matched_index, received) + + def check_ipv4_route(self, src_port, dst_ip_addr, dst_port_list): ''' @summary: Check IPv4 route works. - @param source_port_index: index of port to use for sending packet to switch + @param src_port: index of port to use for sending packet to switch @param dest_ip_addr: destination IP to build packet with. - @param destination_port_list: list of ports on which to expect packet to come back from the switch - @return Boolean + @param dst_port_list: list of ports on which to expect packet to come back from the switch ''' sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = "10.0.0.1" - ip_dst = dest_ip_addr - + ip_dst = dst_ip_addr src_mac = self.dataplane.get_mac(0, 0) pkt = simple_tcp_packet( @@ -196,35 +169,26 @@ def check_ipv4_route(self, source_port_index, dest_ip_addr, destination_port_lis tcp_dport=dport, ip_ttl=63) masked_exp_pkt = Mask(exp_pkt) - masked_exp_pkt.set_do_not_care_scapy(scapy.Ether,"dst") - - send_packet(self, source_port_index, pkt) + masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") - (received_port_index, received) = self.verify_packet_any_port(masked_exp_pkt,destination_port_list) + send_packet(self, src_port, pkt) + logging.info("Sending packet from port " + str(src_port) + " to " + ip_dst) - if not received: - logging.error("Packet sent from %d to %s...Failed" % (source_port_index, dest_ip_addr)) - assert(False) # Fail the test immediately - else: - logging.debug("Packet sent from %d to %s...OK received at %d" % - (source_port_index, dest_ip_addr, received_port_index)) - - return (received_port_index, received) + return verify_packet_any_port(self, masked_exp_pkt, dst_port_list) #--------------------------------------------------------------------- - def check_ipv6_route(self, source_port_index, dest_ip_addr, destination_port_list): + def check_ipv6_route(self, src_port, dst_ip_addr, dst_port_list): ''' @summary: Check IPv6 route works. @param source_port_index: index of port to use for sending packet to switch @param dest_ip_addr: destination IP to build packet with. - @param destination_port_list: list of ports on which to expect packet to come back from the switch + @param dst_port_list: list of ports on which to expect packet to come back from the switch @return Boolean ''' sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = '2000::1' - ip_dst = dest_ip_addr - + ip_dst = dst_ip_addr src_mac = self.dataplane.get_mac(0, 0) pkt = simple_tcpv6_packet( @@ -245,9 +209,10 @@ def check_ipv6_route(self, source_port_index, dest_ip_addr, destination_port_lis masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether,"dst") - send_packet(self, source_port_index, pkt) + send_packet(self, src_port, pkt) + logging.info("Sending packet from port " + str(src_port) + " to " + ip_dst) - return self.verify_packet_any_port(masked_exp_pkt,destination_port_list) + return verify_packet_any_port(self, masked_exp_pkt, dst_port_list) #--------------------------------------------------------------------- def check_within_expected_range(self, actual, expected): ''' @@ -260,7 +225,7 @@ def check_within_expected_range(self, actual, expected): ''' print "%10s" % str(round(percentage, 4)*100) + '%' ''' - return (percentage, abs(percentage) <= self.EXPECTED_RANGE) + return (percentage, abs(percentage) <= self.balancing_range) #--------------------------------------------------------------------- def check_balancing(self, dest_port_list, port_hit_cnt): @@ -278,7 +243,7 @@ def check_balancing(self, dest_port_list, port_hit_cnt): for ecmp_entry in dest_port_list: total_entry_hit_cnt = 0.0 for member in ecmp_entry: - total_entry_hit_cnt += port_hit_cnt[member] + total_entry_hit_cnt += port_hit_cnt.get(member, 0) (p, r) = self.check_within_expected_range(total_entry_hit_cnt, total_hit_cnt/len(dest_port_list)) logging.info("%-10s \t %10d \t %10d \t %10s" % (str(ecmp_entry), total_hit_cnt/len(dest_port_list), total_entry_hit_cnt, str(round(p, 4)*100) + '%')) @@ -286,64 +251,23 @@ def check_balancing(self, dest_port_list, port_hit_cnt): if len(ecmp_entry) == 1: continue for member in ecmp_entry: - (p, r) = self.check_within_expected_range(port_hit_cnt[member], total_entry_hit_cnt/len(ecmp_entry)) + (p, r) = self.check_within_expected_range(port_hit_cnt.get(member, 0), total_entry_hit_cnt/len(ecmp_entry)) logging.info("%-10s \t %10d \t %10d \t %10s" - % (str(member), total_entry_hit_cnt/len(ecmp_entry), port_hit_cnt[member], str(round(p, 4)*100) + '%')) + % (str(member), total_entry_hit_cnt/len(ecmp_entry), port_hit_cnt.get(member, 0), str(round(p, 4)*100) + '%')) result &= r - return result + assert result #--------------------------------------------------------------------- def runTest(self): """ - @summary: Send packet for each route and validate it arrives - on one of expected ECMP ports + @summary: Send packet for each range of both IPv4 and IPv6 spaces and + expect the packet to be received from one of the expected ports """ - exp_port_list = [] - for ecmp_entry in self.dest_port_list: - for port in ecmp_entry: - exp_port_list.append(port) - - ip4_route_cnt = 0 - ip6_route_cnt = 0 - ip4_hit_cnt = 0 - ip6_hit_cnt = 0 - port_cnt_dict = {} - - for i in self.source_port_list: - port_cnt_dict[i] = 0 - - for dest_ip in self.route_list: - for src_port in self.source_port_list: - if self.is_ipv4_address(dest_ip): - ip4_route_cnt += 1 - (matched_index, received) = self.check_ipv4_route(src_port, dest_ip, exp_port_list) - if received: - ip4_hit_cnt += 1 - port_cnt_dict[exp_port_list[matched_index]] = port_cnt_dict.setdefault(exp_port_list[matched_index], 0) + 1 - elif self.is_ipv6_address(dest_ip): - continue - ip6_route_cnt += 1 - (matched_index, received) = self.check_ipv6_route(src_port, dest_ip, exp_port_list) - if received: - ip6_hit_cnt += 1 - port_cnt_dict[exp_port_list[matched_index]] = port_cnt_dict.setdefault(exp_port_list[matched_index], 0) + 1 - else: - print 'Invalid IP address:%s' % dest_ip_addr - assert(False) - - ch = logging.StreamHandler(sys.stdout) - ch.setLevel(logging.DEBUG) - ch.terminator = "" - logging.getLogger().addHandler(ch) - - # Check if sent/received counts are matched - logging.info("\n") - logging.info("--------------------------- TEST RESULT ------------------------------") - logging.info("Sent %d IPv4 packets; recieved %d IPv4 packets" % (ip4_route_cnt, ip4_hit_cnt)) - logging.info("Sent %d IPv6 packets; recieved %d IPv6 packets" % (ip6_route_cnt, ip6_hit_cnt)) - logging.info("----------------------------------------------------------------------") - balancing_result = self.check_balancing(self.dest_port_list, port_cnt_dict) - assert (ip4_route_cnt == ip4_hit_cnt) and (ip6_route_cnt == ip6_hit_cnt) and balancing_result - #--------------------------------------------------------------------- + # IPv4 Test + if (self.test_ipv4): + self.check_ip_range() + # IPv6 Test + if (self.test_ipv6): + self.check_ip_range(ipv4=False) diff --git a/ansible/roles/test/files/ptftests/lpm.py b/ansible/roles/test/files/ptftests/lpm.py new file mode 100644 index 00000000000..f30fdcef4e9 --- /dev/null +++ b/ansible/roles/test/files/ptftests/lpm.py @@ -0,0 +1,105 @@ +import random + +from ipaddress import ip_address, ip_network +from SubnetTree import SubnetTree + +''' +LpmDict is a class used in FIB test for LPM and IP segmentation. + +This class contains a class variable SubnetTree() _subnet_tree to solve the +LPM search functionality, which is achieved using Patricia tree. In order to +have IP segmentation functionality: segment the whole IP space into different +segments from start to end according to the prefixes (networks) it reads. + +Initially, the whole IP space contains only one range. After inserting +prefixes, the IP space is segmented into multiple ranges. The ranges() +function returns all ranges in the LpmDict with a list of IpIntervals. The +sub-class IpInterval then could be used to get the first/last/random IP within +this range. It could also check the length of the range and if an IP is within +this range. + +To achieve the LPM functionality, use the LpmDict as a dictionary and use +[] operator to get the corresponding value using the key (IP). + +Please check the test_lpm.py file to see the details of how this class works. +''' +class LpmDict(): + class IpInterval: + def __init__(self, s): + self._start = s + self._end = s + + def __init__(self, s, e): + assert s <= e + self._start = s + self._end = e + + # __len__ has hard limit on returning long int + def length(self): + return int(self._end) - int(self._start) + + def contains(self, ip): + return ip >= self._start and ip <= self._end + + def get_first_ip(self): + return str(self._start) + + def get_last_ip(self): + return str(self._end) + + def get_random_ip(self): + diff = self.length() + return str(self._start + random.randint(0, diff)) + + def __str__(self): + return str(self._start) + ' - ' + str(self._end) + + def __init__(self, ipv4=True): + self._ipv4 = ipv4 + self._prefix_set = set() + self._subnet_tree = SubnetTree() + # 0.0.0.0 is a non-routable meta-address that needs to be skipped + self._boundaries = { ip_address(u'0.0.0.0') : 1} if ipv4 else { ip_address(u'::') : 1} + + def __setitem__(self, key, value): + prefix = ip_network(unicode(key)) + # add the current key to self._prefix_set only when it is not the default route and it is not a duplicate key + if prefix.prefixlen and key not in self._prefix_set: + boundary = prefix[0] + self._boundaries[boundary] = self._boundaries.get(boundary, 0) + 1 + if prefix[-1] != ip_address(u'255.255.255.255') and prefix[-1] != ip_address(u'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'): + next_boundary = prefix[-1] + 1 + self._boundaries[next_boundary] = self._boundaries.get(next_boundary, 0) + 1 + self._prefix_set.add(key) + self._subnet_tree.__setitem__(key, value) + + def __getitem__(self, key): + return self._subnet_tree[key] + + def __delitem__(self, key): + if '/0' not in key: + prefix = ip_network(unicode(key)) + boundary = prefix[0] + next_boundary = prefix[-1] + 1 + self._boundaries[boundary] = self._boundaries.get(boundary) - 1 + if not self._boundaries[boundary]: + del self._boundaries[boundary] + self._boundaries[next_boundary] = self._boundaries.get(next_boundary) - 1 + if not self._boundaries[next_boundary]: + del self._boundaries[next_boundary] + self._prefix_set.remove(key) + self._subnet_tree.__delitem__(key) + + def ranges(self): + sorted_boundaries = sorted(self._boundaries.keys()) + ranges = [] + for index, boundary in enumerate(sorted_boundaries): + if index != len(sorted_boundaries) - 1: + interval = self.IpInterval(sorted_boundaries[index], sorted_boundaries[index + 1] - 1) + else: + if self._ipv4: + interval = self.IpInterval(sorted_boundaries[index], ip_address(u'255.255.255.255')) + else: + interval = self.IpInterval(sorted_boundaries[index], ip_address(u'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')) + ranges.append(interval) + return ranges diff --git a/ansible/roles/test/files/ptftests/remote.py b/ansible/roles/test/files/ptftests/remote.py index 85e864a446e..9c36653116d 100644 --- a/ansible/roles/test/files/ptftests/remote.py +++ b/ansible/roles/test/files/ptftests/remote.py @@ -36,4 +36,3 @@ def platform_config_update(config): remote_port_map = {(0, i) : v for i, v in enumerate(get_ifaces())} config["port_map"] = remote_port_map.copy() config["caps_table_idx"] = 0 - diff --git a/ansible/roles/test/files/supervisor/arp_responder.conf b/ansible/roles/test/files/supervisor/arp_responder.conf new file mode 100644 index 00000000000..ce265452f56 --- /dev/null +++ b/ansible/roles/test/files/supervisor/arp_responder.conf @@ -0,0 +1,10 @@ +[program:arp_responder] +command=/usr/bin/python /opt/arp_responder.py +process_name=arp_responder +stdout_logfile=/tmp/arp_responder.out.log +stderr_logfile=/tmp/arp_responder.err.log +redirect_stderr=false +autostart=false +autorestart=true +startsecs=1 +numprocs=1 diff --git a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml index 8cda128620d..bb2dae21996 100644 --- a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml +++ b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml @@ -8,7 +8,7 @@ - debug: msg={{cmd}} -- name: Initialize loganalyzer {{ testname }} +- name: Invoke loganalyzer analyse {{ testname }} become: True shell: "{{ cmd }}" args: diff --git a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_end.yml b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_end.yml index f5f570ac29e..5fa944b8afd 100644 --- a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_end.yml +++ b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_end.yml @@ -3,24 +3,45 @@ #------------------------------------------------ - set_fact: - result_file: result.loganalysis.{{testname_unique}}.log - summary_file: summary.loganalysis.{{testname_unique}}.log -- debug : msg="summary_file {{summary_file}}" + result_file: result.loganalysis.{{ testname_unique }}.log + summary_file: summary.loganalysis.{{ testname_unique }}.log + test_fetch_dir: test/{{ inventory_hostname }} + +# Output content of result files to ansible console +- shell: cat {{ test_out_dir }}/* + register: out +- debug: var=out.stdout_lines + +- name: Check if loganalyzer found any error + shell: grep "TOTAL MATCHES" "{{ test_out_dir }}/{{ summary_file }}" | sed -n "s/TOTAL MATCHES:[[:space:]]*//p" + register: errors_found + +- set_fact: + fail_in_logs: errors_found.stdout != "0" + +- name: Generate system dump + command: sonic_support + register: sonic_support + when: fail_in_logs + - name : Fetch result files from switch to ansible machine - fetch: src={{ test_out_dir }}/{{item}} dest=/tmp + fetch: + src: "{{ item }}" + dest: "{{ test_fetch_dir }}/{{ item | basename }}" + flat: yes with_items: - - "{{result_file}}" - - "{{summary_file}}" - -- name : Create destination directory on PTF host for loganalyzer results - file: path="{{ test_out_dir }}" state=directory - delegate_to: "{{ ptf_host }}" + - "{{ test_out_dir }}/{{result_file}}" + - "{{ test_out_dir }}/{{summary_file}}" + - "{{ sonic_support.stdout | default(omit) }}" + when: fail_in_logs -- name: Copy loganalyzer result files from ansible machine to PTF host - copy: src="/tmp/{{inventory_hostname}}/{{test_out_dir}}/{{item}}" dest="{{ test_out_dir }}/{{item}}" +- debug: msg="File {{ item }} saved to {{ test_fetch_dir }}" with_items: - - "{{ result_file }}" - - "{{ summary_file }}" - delegate_to: "{{ ptf_host }}" + - "{{result_file}}" + - "{{summary_file}}" + - "{{ sonic_support.stdout | default(omit) }}" + when: fail_in_logs -- debug: msg="Location of log files on PTF host - {{ test_out_dir }}" \ No newline at end of file +- name: Fail due to errors in logs + fail: + when: fail_in_logs diff --git a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_init.yml b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_init.yml index 586c2807b88..4ace815cefe 100644 --- a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_init.yml +++ b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_init.yml @@ -27,6 +27,8 @@ - name: create output directory for current test run file: path="{{ test_out_dir }}" state=directory +- name: Force log rotation to have most of log file available + command: logrotate -f /etc/logrotate.conf - debug: msg="starting loganalyzer_init.py" - debug: msg="python {{ run_dir }}/loganalyzer.py --action init --run_id {{ testname_unique }}" diff --git a/ansible/roles/test/tasks/acltb.yml b/ansible/roles/test/tasks/acltb.yml index c4dd9f52d9f..bd10a48bb89 100644 --- a/ansible/roles/test/tasks/acltb.yml +++ b/ansible/roles/test/tasks/acltb.yml @@ -18,10 +18,3 @@ - name: Clean up ACL test configuration on the testbed include: acltb_cleanup.yml tags: acltb_cleanup - -#----------------------------------------- -# Run ACL ranges count test -#----------------------------------------- -- name: Acl ranges count test - include: acltb_ranges_test.yml - tags: acltb_ranges_test diff --git a/ansible/roles/test/tasks/acltb_cleanup.yml b/ansible/roles/test/tasks/acltb_cleanup.yml index b829830162e..290229e4c70 100644 --- a/ansible/roles/test/tasks/acltb_cleanup.yml +++ b/ansible/roles/test/tasks/acltb_cleanup.yml @@ -14,6 +14,7 @@ test_expect_file: acltb_expect_messages.txt match_file: loganalyzer_common_match.txt ignore_file: loganalyzer_common_ignore.txt + tests_location: "{{ 'roles/test/tasks' }}" # Separate set_fact is required to be able to use 'testname' fact. - set_fact: @@ -35,7 +36,7 @@ - name: Read port reverse alias mapping set_fact: - alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}" + alias_reverse_map: "{{ minigraph_map_ngs_to_sonic }}" # Generate json files with ACL configuration for tests - template: src=acltb_test_table.j2 dest=/tmp/acltb_test_table.json @@ -60,33 +61,8 @@ with_items: - "{{ acltb_configs }}" -- include: roles/test/files/tools/loganalyzer/loganalyzer_init.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" - - block: - name: Apply ACL delete configuration command: docker exec -t swss bash -c "swssconfig /etc/swss/config.d/{{ item }}" with_items: - "{{ acltb_configs }}" - always: - - include: roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" - - # Output content of result files to ansible console - - shell: cat {{ test_out_dir }}/* - register: out - - debug: var=out.stdout_lines - - - name: Get the total number of error messages. - shell: grep "TOTAL MATCHES" "{{ test_out_dir }}/{{ summary_file }}" | sed -n "s/TOTAL MATCHES:[[:space:]]*//p" - register: errors_found - - - name: Check the number of error messages (positive tests only). - fail: msg="{{ errors_found.stdout }} errors found while running {{ testname }} test. Please see {{ test_out_dir }}/{{ result_file }}" - when: errors_found.stdout != "0" - - - include: roles/test/files/tools/loganalyzer/loganalyzer_end.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" diff --git a/ansible/roles/test/tasks/acltb_configure.yml b/ansible/roles/test/tasks/acltb_configure.yml index 278dbab4c1f..44915a0e789 100644 --- a/ansible/roles/test/tasks/acltb_configure.yml +++ b/ansible/roles/test/tasks/acltb_configure.yml @@ -14,6 +14,7 @@ test_expect_file: acltb_expect_messages.txt match_file: loganalyzer_common_match.txt ignore_file: loganalyzer_common_ignore.txt + tests_location: "{{ 'roles/test/tasks' }}" # Separate set_fact is required to be able to use 'testname' fact. - set_fact: @@ -35,7 +36,8 @@ - name: Read port reverse alias mapping set_fact: - alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}" + alias_reverse_map: "{{ minigraph_map_ngs_to_sonic }}" + podset_number: 200 # Generate json files with ACL configuration for tests - template: src=acltb_test_table.j2 dest=/tmp/acltb_test_table.json @@ -55,33 +57,8 @@ with_items: - "{{ acltb_configs }}" -- include: roles/test/files/tools/loganalyzer/loganalyzer_init.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" - - block: - name: Apply ACL configuration command: docker exec -t swss bash -c "swssconfig /etc/swss/config.d/{{ item }}" with_items: - "{{ acltb_configs }}" - always: - - include: roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" - - # Output content of result files to ansible console - - shell: cat {{ test_out_dir }}/* - register: out - - debug: var=out.stdout_lines - - - name: Get the total number of error messages. - shell: grep "TOTAL MATCHES" "{{ test_out_dir }}/{{ summary_file }}" | sed -n "s/TOTAL MATCHES:[[:space:]]*//p" - register: errors_found - - - name: Check the number of error messages (positive tests only). - fail: msg="{{ errors_found.stdout }} errors found while running {{ testname }} test. Please see {{ test_out_dir }}/{{ result_file }}" - when: errors_found.stdout != "0" - - - include: roles/test/files/tools/loganalyzer/loganalyzer_end.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" diff --git a/ansible/roles/test/tasks/acltb_test.yml b/ansible/roles/test/tasks/acltb_test.yml index df36b2d4ee7..30a6f74864e 100644 --- a/ansible/roles/test/tasks/acltb_test.yml +++ b/ansible/roles/test/tasks/acltb_test.yml @@ -19,7 +19,7 @@ - name: Read port reverse alias mapping set_fact: - alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}" + alias_reverse_map: "{{ minigraph_map_ngs_to_sonic }}" - name: Expand properties into props set_fact: props="{{configuration_properties['spine']}}" @@ -42,6 +42,7 @@ test_expect_file: acltb_expect_messages.txt match_file: loganalyzer_common_match.txt ignore_file: loganalyzer_common_ignore.txt + tests_location: "{{ 'roles/test/tasks' }}" # Separate set_fact is required to be able to use 'testname' fact. - set_fact: @@ -60,10 +61,6 @@ copy: src=roles/test/files/acstests/acltb_test.py dest=/root/test/ delegate_to: "{{ ptf_host }}" -- include: roles/test/files/tools/loganalyzer/loganalyzer_init.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" - # Run the ACL PTF test - block: - name: Run the test @@ -77,25 +74,3 @@ - verbose=True - router_mac=\"{{ ansible_Ethernet0['macaddress'] }}\" - switch_info=\"/tmp/acltb_switch_info.txt\" - - always: - - include: roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" - - # Output content of result files to ansible console - - shell: cat {{ test_out_dir }}/* - register: out - - debug: var=out.stdout_lines - - - name: Get the total number of error messages. - shell: grep "TOTAL MATCHES" "{{ test_out_dir }}/{{ summary_file }}" | sed -n "s/TOTAL MATCHES:[[:space:]]*//p" - register: errors_found - - - name: Check the number of error messages (positive tests only). - fail: msg="{{ errors_found.stdout }} errors found while running {{ testname }} test. Please see {{ test_out_dir }}/{{ result_file }}" - when: errors_found.stdout != "0" - - - include: roles/test/files/tools/loganalyzer/loganalyzer_end.yml - vars: - tests_location: "{{ 'roles/test/tasks' }}" diff --git a/ansible/roles/test/tasks/arpall.yml b/ansible/roles/test/tasks/arpall.yml index 3bcd65fb0d4..e891ae9aaf8 100644 --- a/ansible/roles/test/tasks/arpall.yml +++ b/ansible/roles/test/tasks/arpall.yml @@ -55,7 +55,7 @@ assert: that: - "'{{ item.key }}|string' != '10.10.1.4'" - with_dict: arptable2.arptable.v4 + with_dict: "{{ arptable2.arptable.v4 }}" ## check DUT won't reply ARP and install ARP entry when src address is not in interface subnet range - name: Clear DUT arp cache @@ -76,7 +76,7 @@ assert: that: - "'{{ item.key }}|string' != '10.10.1.22'" - with_dict: arptable3.arptable.v4 + with_dict: "{{ arptable3.arptable.v4 }}" ## Test Gratuitous ARP behavior, no Gratuitous ARP installed when arp was not resolved before - name: Clear DUT arp cache @@ -97,7 +97,7 @@ assert: that: - "'{{ item.key }}|string' != '10.10.1.7'" - with_dict: arptable5.arptable.v4 + with_dict: "{{ arptable5.arptable.v4 }}" # Test Gratuitous ARP update case, when received garp, no arp reply, update arp table if it was solved before - name: Send correct arp packets (10.10.1.3 to 10.10.1.2 with src_mac=00:06:07:08:09:0a) @@ -136,8 +136,8 @@ # Recover DUT interface IP Address before entering this test case - name: Recover DUT IP address based on minigraph - command: /sbin/ifconfig {{item.name}} {{ item.addr }} netmask {{ item.mask }} + command: /sbin/ifconfig {{item.attachto}} {{ item.addr }} netmask {{ item.mask }} become: yes - with_items: minigraph_interfaces - when: item.name == 'Ethernet4' or item.name == 'Ethernet8' + with_items: "{{ minigraph_interfaces }}" + when: (item.attachto == 'Ethernet4' or item.attachto == 'Ethernet8') and item.addr|ipv4 diff --git a/ansible/roles/test/tasks/base_sanity.yml b/ansible/roles/test/tasks/base_sanity.yml new file mode 100644 index 00000000000..1e0f26436f1 --- /dev/null +++ b/ansible/roles/test/tasks/base_sanity.yml @@ -0,0 +1,18 @@ + - name: Get process information in syncd docker + shell: docker exec -i syncd ps aux | grep /usr/bin/syncd + register: ps_out + + - debug: var=ps_out.stdout_lines + + - name: Verify that syncd process is running + assert: { that: "{{ ps_out.stdout_lines | length }} > 0"} + + - name: Get syslog error information + shell: cat /var/log/syslog |tail -n 5000 |grep -i error + become: true + register: syslog_out + failed_when: false + + - debug: var=syslog_out.stdout_lines + + diff --git a/ansible/roles/test/tasks/bgp_flap.yml b/ansible/roles/test/tasks/bgp_flap.yml index 192886cb298..e9987917e52 100644 --- a/ansible/roles/test/tasks/bgp_flap.yml +++ b/ansible/roles/test/tasks/bgp_flap.yml @@ -1,4 +1,3 @@ -# Shuotian Cheng # # This test is part of sswsyncd functionality tests. # @@ -7,18 +6,17 @@ # nexthopgroup table is updated according to the certain BGP session flappings. - set_fact: acs_devices: "{{ minigraph_devices }}" - bgp_neighbors: "{{ minigraph_bgp }}" - debug: var=sonic_asic_type - set_fact: asic="{{ sonic_asic_type }}" - include: bgp_nei_up.yml - with_items: bgp_neighbors + with_items: "{{ minigraph_bgp }}" when: "'T2' in item['name']" - include: bgp_entry_flap.yml - with_items: bgp_neighbors + with_items: "{{ minigraph_bgp }}" - name: recover minigraph facts about the device(above steps loaded neighbors configuration) minigraph_facts: host="{{ inventory_hostname }}" diff --git a/ansible/roles/test/tasks/decap.yml b/ansible/roles/test/tasks/decap.yml index 8bfb84e01c4..f8e17ebe6e5 100644 --- a/ansible/roles/test/tasks/decap.yml +++ b/ansible/roles/test/tasks/decap.yml @@ -1,42 +1,51 @@ #----------------------------------------- -# Run Decap test and Perform log analysis. +# Run Decap test #----------------------------------------- - fail: msg="information about testbed missing." when: (testbed_type is not defined) or - (lo_ip is not defined) or (dscp_mode is not defined) - fail: msg="Invalid testbed_type value '{{testbed_type}}'" - when: testbed_type not in [ 'fib'] + when: testbed_type not in [ 't1', 't0', 't1-lag'] - fail: msg="Invalid testbed_type value '{{dscp_mode}}'" when: dscp_mode not in [ 'pipe','uniform'] +- include_vars: "vars/topo_{{testbed_type}}.yml" + +- name: Expand properties into props + set_fact: props="{{configuration_properties['spine']}}" + when: testbed_type in ['t1', 't1-lag'] + +- name: Expand properties into props + set_fact: props="{{configuration_properties['common']}}" + when: testbed_type in ['t0'] + +- name: Expand properties into props + set_fact: props_tor="{{configuration_properties['tor']}}" + when: testbed_type in ['t1', 't1-lag'] + # Gather minigraph facts - name: Gathering minigraph facts about the device minigraph_facts: host={{ inventory_hostname }} become: no connection: local -- name: Print neighbors in minigraph - debug: msg="{{ minigraph_neighbors }}" +# Obtain loopback ip of the device +- name: Obtain loopback ip of the device + set_fact: lo_ip="{{ minigraph_lo_interfaces[0]['addr'] }}" -- name: Read port reverse alias mapping - set_fact: - alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}" - -- name: Print alias reverse mapping - debug: msg="{{ alias_reverse_map }}" +- name: print loopback ip + debug: msg="{{ lo_ip }}" # Generate file with BGP routes information -- template: src=fib.j2 dest=/tmp/fib.txt +- template: src=roles/test/templates/fib.j2 dest=/tmp/fib_info.txt connection: local - - -- name: Copy route into file to the PTF host - copy: src="/tmp/fib.txt" dest="/tmp/route_info.txt" +# Copy the fib_info to ptf container +- template: src=/tmp/fib_info.txt dest=/root + connection: local delegate_to: "{{ ptf_host }}" - set_fact: @@ -61,39 +70,21 @@ ignore_file_list: "{{ run_dir }}/{{test_ignore_file}},{{ run_dir }}/{{ignore_file}}" - debug: msg="output directory for current test run {{ test_out_dir }}" -- debug: msg="generated run id:{{testname_unique}}" -- include: roles/test/files/tools/loganalyzer/loganalyzer_init.yml +- debug: msg="generated run id:{{testname_unique}}" - debug : msg="INVOKE DECAP TEST" -- block: - - - - - name: copy the test to ptf container - copy: src=roles/test/files/acstests dest=/root - delegate_to: "{{ ptf_host }}" - - - name: "Running test {{ testname }}" - shell: ptf --test-dir acstests IP_decap_test --platform remote -t "verbose=True; router_mac='{{ ansible_Ethernet0['macaddress'] }}';lo_ip='{{lo_ip}}';dscp_mode='{{dscp_mode}}'; route_info='/tmp/route_info.txt'" --relax - args: - chdir: /root - delegate_to: "{{ ptf_host }}" - register: out - - - debug: var=out.stdout_lines - when: out.rc != 0 - - always: - - - - - include: roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml - - # Output content of result files to ansible console - - shell: cat {{ test_out_dir }}/* - register: out - - debug: var=out.stdout_lines - - - include: roles/test/files/tools/loganalyzer/loganalyzer_end.yml +- name: copy the test to ptf container + copy: src=roles/test/files/ptftests dest=/root + delegate_to: "{{ ptf_host }}" + +- name: "Running test {{ testname }}" + shell: ptf --test-dir ptftests IP_decap_test --platform remote -t "verbose=True; router_mac='{{ ansible_Ethernet0['macaddress'] }}';lo_ip='{{lo_ip}}';dscp_mode='{{dscp_mode}}'; testbed_type='{{testbed_type}}'; fib_info='/root/fib_info.txt'" --relax + args: + chdir: /root + delegate_to: "{{ ptf_host }}" + failed_when: False + register: out + +- debug: var=out.stdout_lines diff --git a/ansible/roles/test/tasks/dhcp_relay.yml b/ansible/roles/test/tasks/dhcp_relay.yml index f4931b8351a..c9fa80d8efe 100644 --- a/ansible/roles/test/tasks/dhcp_relay.yml +++ b/ansible/roles/test/tasks/dhcp_relay.yml @@ -1,12 +1,11 @@ # We choose client port index to be index of first port on Vlan - name: Obtain client port index set_fact: - client_port_name: "{{ minigraph_vlan_interfaces[0]['members'].split(' ')[0] }}" + client_port_name: "{{ minigraph_vlans[minigraph_vlans.keys()[0]]['members'][0] }}" - set_fact: client_port_index: "{{ minigraph_port_indices[client_port_name] }}" - - name: Obtain leaf port indices set_fact: leaf_port_indices: [] @@ -16,27 +15,23 @@ with_dict: "{{ minigraph_neighbors }}" when: minigraph_devices[item.value.name] is defined and minigraph_devices[item.value.name]['type'] == "LeafRouter" - -- name: Obtain MAC address of {{ minigraph_vlan_interfaces[0]['name'] }} interface +- name: Obtain MAC address of {{ minigraph_vlan_interfaces[0]['attachto'] }} interface become: true - shell: "cat /sys/class/net/{{ minigraph_vlan_interfaces[0]['name'] }}/address" + shell: "cat /sys/class/net/{{ minigraph_vlan_interfaces[0]['attachto'] }}/address" register: result - set_fact: relay_iface_mac: "{{ result.stdout | from_yaml }}" - -- name: Copy the DHCP relay test to PTF container - become: true - copy: src=roles/test/files/ptftests/dhcp_relay_test.py dest=/root/test/ +- name: Copy tests to the PTF container + copy: src=roles/test/files/ptftests dest=/root delegate_to: "{{ ptf_host }}" - # Run the DHCP relay PTF test - include: ptf_runner.yml vars: ptf_test_name: DHCP Relay Test - ptf_test_dir: test + ptf_test_dir: ptftests ptf_test_path: dhcp_relay_test.DHCPTest ptf_platform: remote ptf_test_params: @@ -44,7 +39,7 @@ - leaf_port_indices=\"{{ leaf_port_indices }}\" - num_dhcp_servers=\"{{ dhcp_servers | length }}\" - server_ip=\"{{ dhcp_servers[0] }}\" - - relay_iface_name=\"{{ minigraph_vlan_interfaces[0]['name'] }}\" + - relay_iface_name=\"{{ minigraph_vlan_interfaces[0]['attachto'] }}\" - relay_iface_ip=\"{{ minigraph_vlan_interfaces[0]['addr'] }}\" - relay_iface_mac=\"{{ relay_iface_mac }}\" - relay_iface_netmask=\"{{ minigraph_vlan_interfaces[0]['mask'] }}\" diff --git a/ansible/roles/test/tasks/ecmp.yml b/ansible/roles/test/tasks/ecmp.yml index 930adc26b92..9af35579c11 100644 --- a/ansible/roles/test/tasks/ecmp.yml +++ b/ansible/roles/test/tasks/ecmp.yml @@ -1,27 +1,4 @@ - block: - - name: Ensure LLDP Daemon stopped - become: yes - supervisorctl: state=stopped name={{ item }} - vars: - ansible_shell_type: docker - ansible_python_interpreter: docker exec -i lldp python - with_items: - - lldp-syncd - - lldpd - - - name: Disable bgpd - become: yes - lineinfile: dest=/etc/quagga/daemons - regexp=^bgpd=.*$ - line='bgpd=no' - notify: - - Restart Quagga Daemon - vars: - ansible_shell_type: docker - ansible_python_interpreter: docker exec -i bgp python - - - meta: flush_handlers - - fail: msg="Please set ptf_host variable" when: ptf_host is not defined @@ -60,7 +37,7 @@ debug: var=out.stdout_lines - name: copy the test to ptf container - copy: src=roles/test/files/saitests dest=/root + copy: src=roles/test/files/ptftests dest=/root delegate_to: "{{ ptf_host }}" - name: Install routes on the switch @@ -92,12 +69,18 @@ - name: Output of the arp table on target host {{ ansible_host }} debug: var=out.stdout_lines - - include: qos_sai_ptf.yml + - include: ptf_runner.yml vars: - test_name: ECMP test - test_path: ecmp_test.ECMPtest - test_params: "" - extra_options: "--relax --log-dir /tmp/" + ptf_test_name: ECMP test + ptf_test_dir: ptftests + ptf_test_path: ecmp_test.ECMPtest + ptf_platform: remote + ptf_test_params: + - verbose=True + - server='{{ ansible_host }}' + - port_map_file='/root/{{ ptf_portmap | basename }}' + - router_mac='{{ ansible_Ethernet0['macaddress'] }}' + ptf_extra_options: "--relax --log-dir /tmp/" always: - name: Remove routes from the switch @@ -106,26 +89,3 @@ - name: Remove existing ip from ptf host script: roles/test/files/helpers/remove_ip.sh delegate_to: "{{ ptf_host }}" - - - name: Restore LLDP Daemon - become: yes - supervisorctl: state=started name={{ item }} - vars: - ansible_shell_type: docker - ansible_python_interpreter: docker exec -i lldp python - with_items: - - lldpd - - lldp-syncd - - - name: Enable bgpd - become: yes - lineinfile: dest=/etc/quagga/daemons - regexp=^bgpd=.*$ - line='bgpd=yes' - notify: - - Restart Quagga Daemon - vars: - ansible_shell_type: docker - ansible_python_interpreter: docker exec -i bgp python - - - meta: flush_handlers diff --git a/ansible/roles/test/tasks/everflow_testbed.yml b/ansible/roles/test/tasks/everflow_testbed.yml index 86579dee3cc..d8299d0ef9e 100644 --- a/ansible/roles/test/tasks/everflow_testbed.yml +++ b/ansible/roles/test/tasks/everflow_testbed.yml @@ -1,9 +1,3 @@ -# Run command: -# cd ansible -# ansible-playbook test_sonic.yml -i inventory --limit -b --tags everflow_tb_configure -e ptf_host= -vvvvv -# ansible-playbook test_sonic.yml -i inventory --limit -b --tags everflow_tb_test -e ptf_host=ptf-fib -e testbed_type= -vvvv -# ansible-playbook test_sonic.yml -i inventory --limit -b --tags everflow_tb_cleanup -e ptf_host= -vvvvv - - name: Apply Everflow configuration. include: "roles/test/tasks/everflow_testbed/apply_config.yml" tags: everflow_tb_configure diff --git a/ansible/roles/test/tasks/everflow_testbed/apply_config.yml b/ansible/roles/test/tasks/everflow_testbed/apply_config.yml index 2d05439c78a..f3dded68930 100644 --- a/ansible/roles/test/tasks/everflow_testbed/apply_config.yml +++ b/ansible/roles/test/tasks/everflow_testbed/apply_config.yml @@ -9,10 +9,6 @@ - acl_table.json - acl_rule_persistent.json -- name: Read port reverse alias mapping. - set_fact: - alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}" - - name: Generate json files with ACL configuration for tests template: src={{ tests_location }}/{{ testname }}/acl_table.j2 dest={{ tests_location }}/{{ testname }}/acl_table.json connection: local diff --git a/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_rule_persistent.json b/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_rule_persistent.json index 25b4295ff37..7dcfc5ad481 100644 --- a/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_rule_persistent.json +++ b/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_rule_persistent.json @@ -3,7 +3,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_1": { "priority" : "50", "src_ip" : "20.0.0.10", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -11,7 +11,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_2": { "priority" : "50", "dst_ip" : "30.0.0.10", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -19,7 +19,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_3": { "priority" : "50", "l4_src_port" : "0x1235", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -27,7 +27,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_4": { "priority" : "50", "l4_dst_port" : "0x1235", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -35,7 +35,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_5": { "priority" : "50", "ether_type" : "0x1234", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -43,7 +43,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_6": { "priority" : "50", "ip_protocol" : "0x7E", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -51,7 +51,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_7": { "priority" : "50", "tcp_flags" : "0x12/0x12", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -59,7 +59,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_8": { "priority" : "50", "l4_src_port_range" : "4672-4681", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -67,7 +67,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_9": { "priority" : "50", "l4_dst_port_range" : "4672-4681", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" }, @@ -75,7 +75,7 @@ "ACL_RULE_TABLE:acl_table_mirror:rule_10": { "priority" : "50", "dscp" : "51", - "mirror_action" : "session_1" + "mirror_action" : "test_session_1" }, "OP": "SET" } diff --git a/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.j2 b/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.j2 index e6c1b430522..75a863cfc9b 100644 --- a/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.j2 +++ b/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.j2 @@ -3,7 +3,7 @@ "ACL_TABLE:acl_table_mirror": { "policy_desc" : "Everflow_ACL_table", "type" : "MIRROR", - "ports" : "{% for ifname, v in minigraph_neighbors.iteritems() %}{{"%s" % alias_reverse_map[ifname]}},{% endfor %}" + "ports" : "{% for ifname, v in minigraph_neighbors.iteritems() %}{{"%s" % ifname}},{% endfor %}" }, "OP": "SET" } diff --git a/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.json b/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.json new file mode 100644 index 00000000000..0728edc6f97 --- /dev/null +++ b/ansible/roles/test/tasks/everflow_testbed/apply_config/acl_table.json @@ -0,0 +1,10 @@ +[ + { + "ACL_TABLE:acl_table_mirror": { + "policy_desc" : "Everflow_ACL_table", + "type" : "MIRROR", + "ports" : "Ethernet8,Ethernet0,Ethernet4,Ethernet108,Ethernet100,Ethernet104,Ethernet96,Ethernet124,Ethernet92,Ethernet120,Ethernet52,Ethernet56,Ethernet76,Ethernet72,Ethernet32,Ethernet16,Ethernet36,Ethernet12,Ethernet28,Ethernet88,Ethernet24,Ethernet116,Ethernet80,Ethernet112,Ethernet84,Ethernet48,Ethernet44,Ethernet40,Ethernet64,Ethernet60,Ethernet20,Ethernet68," + }, + "OP": "SET" + } +] diff --git a/ansible/roles/test/tasks/everflow_testbed/apply_config/session.json b/ansible/roles/test/tasks/everflow_testbed/apply_config/session.json index 5015a57f946..0bf7c998620 100644 --- a/ansible/roles/test/tasks/everflow_testbed/apply_config/session.json +++ b/ansible/roles/test/tasks/everflow_testbed/apply_config/session.json @@ -1,6 +1,6 @@ [ { - "MIRROR_SESSION_TABLE:session_1": { + "MIRROR_SESSION_TABLE:test_session_1": { "src_ip": "1.1.1.1", "dst_ip": "2.2.2.2", "gre_type": "0x6558", diff --git a/ansible/roles/test/tasks/everflow_testbed/del_config/session.json b/ansible/roles/test/tasks/everflow_testbed/del_config/session.json index 72f3b2386ed..396ac97f413 100644 --- a/ansible/roles/test/tasks/everflow_testbed/del_config/session.json +++ b/ansible/roles/test/tasks/everflow_testbed/del_config/session.json @@ -1,6 +1,6 @@ [ { - "MIRROR_SESSION_TABLE:session_1": { + "MIRROR_SESSION_TABLE:test_session_1": { }, "OP": "DEL" } diff --git a/ansible/roles/test/tasks/everflow_testbed/get_port_info.yml b/ansible/roles/test/tasks/everflow_testbed/get_port_info.yml index 0f596de827b..bfd739ed6be 100644 --- a/ansible/roles/test/tasks/everflow_testbed/get_port_info.yml +++ b/ansible/roles/test/tasks/everflow_testbed/get_port_info.yml @@ -52,7 +52,7 @@ - name: Define SRC PTF port IDs set_fact: - src_port_ptf_id: "{{ alias_reverse_map[src_port]|replace(\"Ethernet\", \"\")|int / 4 }}" + src_port_ptf_id: "{{ src_port|replace(\"Ethernet\", \"\")|int / 4 }}" - name: Define port variables. set_fact: @@ -67,17 +67,17 @@ - name: Check if DST port in LAG member set_fact: dst_port_1_is_lag_member: "{{ item.members }}" - with_items: "{{ minigraph_portchannel_interfaces }}" + with_items: "{{ minigraph_portchannels.values() }}" when: "dst_port_1 in item.members" - name: Define PTF port IDs for dst_port_1 set_fact: - dst_port_1_ptf_id: "{{ alias_reverse_map[dst_port_1]|replace(\"Ethernet\", \"\")|int / 4 }}" + dst_port_1_ptf_id: "{{ dst_port_1|replace(\"Ethernet\", \"\")|int / 4 }}" when: "not dst_port_1_is_lag_member" - name: Define PTF port IDs for dst_port_1 set_fact: - dst_port_1_ptf_id: "{{ alias_reverse_map[item]|replace(\"Ethernet\", \"\")|int / 4 }},{{ dst_port_1_ptf_id }}" + dst_port_1_ptf_id: "{{ item|replace(\"Ethernet\", \"\")|int / 4 }},{{ dst_port_1_ptf_id }}" with_items: "{{ dst_port_1_is_lag_member }}" when: "dst_port_1_is_lag_member" @@ -96,7 +96,7 @@ - name: Check if DST port in LAG member set_fact: dst_port_2_is_lag_member: "{{ item.members }}" - with_items: "{{ minigraph_portchannel_interfaces }}" + with_items: "{{ minigraph_portchannels.values() }}" when: "dst_port_2 in item.members" - name: Print port channels @@ -105,12 +105,12 @@ - name: Define PTF port IDs for dst_port_2 set_fact: - dst_port_2_ptf_id: "{{ alias_reverse_map[dst_port_2]|replace(\"Ethernet\", \"\")|int / 4 }}" + dst_port_2_ptf_id: "{{ dst_port_2|replace(\"Ethernet\", \"\")|int / 4 }}" when: "not dst_port_2_is_lag_member" - name: Define PTF port IDs for dst_port_2 set_fact: - dst_port_2_ptf_id: "{{ alias_reverse_map[item]|replace(\"Ethernet\", \"\")|int / 4 }},{{ dst_port_2_ptf_id }}" + dst_port_2_ptf_id: "{{ item|replace(\"Ethernet\", \"\")|int / 4 }},{{ dst_port_2_ptf_id }}" with_items: "{{ dst_port_2_is_lag_member }}" when: "dst_port_2_is_lag_member" @@ -129,7 +129,7 @@ - name: Check if DST port in LAG member set_fact: dst_port_3_is_lag_member: "{{ item.members }}" - with_items: "{{ minigraph_portchannel_interfaces }}" + with_items: "{{ minigraph_portchannels.values() }}" when: "dst_port_3 in item.members" - name: Print port channels @@ -138,12 +138,12 @@ - name: Define PTF port IDs for dst_port_3 set_fact: - dst_port_3_ptf_id: "{{ alias_reverse_map[dst_port_3]|replace(\"Ethernet\", \"\")|int / 4 }}" + dst_port_3_ptf_id: "{{ dst_port_3|replace(\"Ethernet\", \"\")|int / 4 }}" when: "not dst_port_3_is_lag_member" - name: Define PTF port IDs for dst_port_3 set_fact: - dst_port_3_ptf_id: "{{ alias_reverse_map[item]|replace(\"Ethernet\", \"\")|int / 4 }},{{ dst_port_3_ptf_id }}" + dst_port_3_ptf_id: "{{ item|replace(\"Ethernet\", \"\")|int / 4 }},{{ dst_port_3_ptf_id }}" with_items: "{{ dst_port_3_is_lag_member }}" when: "dst_port_3_is_lag_member" diff --git a/ansible/roles/test/tasks/everflow_testbed/get_session_info.yml b/ansible/roles/test/tasks/everflow_testbed/get_session_info.yml index fbe64c0ed37..64bd59023e7 100644 --- a/ansible/roles/test/tasks/everflow_testbed/get_session_info.yml +++ b/ansible/roles/test/tasks/everflow_testbed/get_session_info.yml @@ -1,10 +1,6 @@ -- name: Get session name. - shell: docker exec -i swss redis-cli KEYS MIRROR_SESSION_TABLE:* | sed "s/MIRROR_SESSION_TABLE://" - register: session_name_info - - name: Initialize session_name variable. set_fact: - session_name: "{{ session_name_info.stdout }}" + session_name: "test_session_1" - debug: msg="session name {{ session_name }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/run_test.yml b/ansible/roles/test/tasks/everflow_testbed/run_test.yml index f8e9b78dfab..a096ac42102 100644 --- a/ansible/roles/test/tasks/everflow_testbed/run_test.yml +++ b/ansible/roles/test/tasks/everflow_testbed/run_test.yml @@ -16,13 +16,6 @@ - name: Print neighbors in minigraph debug: msg="{{ minigraph_neighbors }}" -- name: Read port reverse alias mapping. - set_fact: - alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}" - -- name: Print alias reverse mapping - debug: msg="{{ alias_reverse_map }}" - - set_fact: testname: everflow_testbed run_dir: /tmp diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_1.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_1.yml index 80c14043d74..ae54ee2285e 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_1.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_1.yml @@ -6,7 +6,7 @@ - block: - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_2.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_2.yml index ae89176b69c..e4c6089a779 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_2.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_2.yml @@ -6,7 +6,7 @@ shell: ip route add {{ session_prefix_1 }} via {{ neighbor_info_1['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -16,7 +16,7 @@ shell: ip route add {{ session_prefix_2 }} via {{ unresolved_nexthop }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -26,7 +26,7 @@ shell: ip route change {{ session_prefix_2 }} via {{ neighbor_info_2['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_3.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_3.yml index f1f763bb598..b6dc10fdf2b 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_3.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_3.yml @@ -6,7 +6,7 @@ shell: ip route add {{ session_prefix_1 }} via {{ neighbor_info_1['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -16,7 +16,7 @@ shell: ip route add {{ session_prefix_2 }} via {{ neighbor_info_2['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_2}}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -27,7 +27,7 @@ ignore_errors: yes - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_4.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_4.yml index 0aded9fefdc..3c622c81bf6 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_4.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_4.yml @@ -6,7 +6,7 @@ shell: ip route add {{ session_prefix_1 }} via {{ neighbor_info_1['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";expected_dst_mac="{{ neighbor_mac_1 }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";expected_dst_mac="{{ neighbor_mac_1 }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -16,7 +16,7 @@ shell: ip neigh replace {{ neighbor_info_1['addr'] }} lladdr "00:11:22:33:44:55" nud permanent dev {{ dst_port_1 }} - name: Send traffic and verify that packets with correct Everflow header are received on destination port {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";expected_dst_mac="00:11:22:33:44:55";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";expected_dst_mac="00:11:22:33:44:55";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_5.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_5.yml index 7521579914a..e041284df13 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_5.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_5.yml @@ -5,7 +5,7 @@ - block: - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }} or {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_6.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_6.yml index aa676290756..2b0b11d89c0 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_6.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_6.yml @@ -6,7 +6,7 @@ shell: ip route add {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} via {{ neighbor_info_2['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }} or {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -16,14 +16,14 @@ shell: ip route change {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} via {{ neighbor_info_2['addr'] }} via {{ neighbor_info_3['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }} or {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" register: out - name: Send traffic and verify that packets are not received on {{ dst_port_3 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_7.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_7.yml index c11d1cf2456..a0d545937fb 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_7.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_7.yml @@ -6,7 +6,7 @@ shell: ip route add {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -16,14 +16,14 @@ shell: ip route change {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} via {{ neighbor_info_2['addr'] }} via {{ neighbor_info_3['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" register: out - name: Send traffic and verify that packets are not received on {{ dst_port_2 }} and {{ dst_port_3 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }},{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }},{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -34,7 +34,7 @@ shell: ip route change {{ session_prefix_1 }} nexthop via {{ neighbor_info_2['addr'] }} via {{ neighbor_info_3['addr'] }} - name: Send traffic and verify that packets are not received {{ dst_port_1 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -42,7 +42,7 @@ failed_when: out.rc == 0 - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_2 }} or {{ dst_port_3 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }},{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_2_ptf_id }},{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml index 6801ccb5532..c5227326442 100644 --- a/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml @@ -6,7 +6,7 @@ shell: ip route add {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} via {{ neighbor_info_2['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }} or {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -16,14 +16,14 @@ shell: ip route change {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} via {{ neighbor_info_2['addr'] }} via {{ neighbor_info_3['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }} or {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" register: out - name: Send traffic and verify that packets are not received on {{ dst_port_3 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -34,14 +34,14 @@ shell: ip route change {{ session_prefix_1 }} nexthop via {{ neighbor_info_1['addr'] }} via {{ neighbor_info_2['addr'] }} - name: Send traffic and verify that packets with correct Everflow header are received on {{ dst_port_1 }} or {{ dst_port_2 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_1_ptf_id }}, {{ dst_port_2_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" register: out - name: Send traffic and verify that packets are not received on {{ dst_port_3 }}. - shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' + shell: ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'hwsku="{{ sonic_hwsku }}";router_mac="{{ ansible_Ethernet0['macaddress'] }}";src_port="{{ src_port_ptf_id }}";dst_ports="{{ dst_port_3_ptf_id }}";session_src_ip="{{ session_src_ip }}";session_dst_ip="{{ session_dst_ip }}";session_ttl="{{ session_ttl }}";session_dscp="{{ session_dscp }}";verbose=True' args: chdir: /root delegate_to: "{{ ptf_host }}" diff --git a/ansible/roles/test/tasks/fast-reboot.yml b/ansible/roles/test/tasks/fast-reboot.yml index 7ee7a376fa6..37b44964e88 100644 --- a/ansible/roles/test/tasks/fast-reboot.yml +++ b/ansible/roles/test/tasks/fast-reboot.yml @@ -10,16 +10,26 @@ script: roles/test/files/helpers/change_mac.sh delegate_to: "{{ ptf_host }}" - - name: Create a directory for the test - file: - path: /root/fast-reboot - state: directory - delegate_to: "{{ ptf_host }}" - - name: Copy tests to the PTF container copy: src=roles/test/files/ptftests dest=/root delegate_to: "{{ ptf_host }}" + - name: Copy arp responder to the PTF container + copy: src=roles/test/files/helpers/arp_responder.py dest=/opt + delegate_to: "{{ ptf_host }}" + + - name: Copy arp responder supervisor configuration to the PTF container + copy: src=roles/test/files/supervisor/arp_responder.conf dest=/etc/supervisor/conf.d + delegate_to: "{{ ptf_host }}" + + - name: Reread supervisor configuration + shell: /usr/bin/supervisorctl reread + delegate_to: "{{ ptf_host }}" + + - name: Update supervisor configuration + shell: /usr/bin/supervisorctl update + delegate_to: "{{ ptf_host }}" + - name: Remove old keys file: path: "{{ item }}" @@ -60,20 +70,20 @@ - name: Copy portchannels to ptf host copy: - content: "{{ minigraph_portchannel_interfaces | to_nice_json }}" + content: "{{ minigraph_portchannels | to_nice_json }}" dest: /tmp/portchannel_interfaces.json delegate_to: "{{ ptf_host }}" - name: Copy vlan_interfaces to ptf host copy: - content: "{{ minigraph_vlan_interfaces | to_nice_json }}" + content: "{{ minigraph_vlans | to_nice_json }}" dest: /tmp/vlan_interfaces.json delegate_to: "{{ ptf_host }}" - - name: Copy port_indices to ptf host + - name: Copy minigraph_ports to ptf host copy: content: "{{ minigraph_port_indices | to_nice_json }}" - dest: /tmp/port_indices.json + dest: /tmp/ports.json delegate_to: "{{ ptf_host }}" - include: ptf_runner.yml @@ -91,12 +101,12 @@ - fast_reboot_limit=30 - portchannel_ports_file=\"/tmp/portchannel_interfaces.json\" - vlan_ports_file=\"/tmp/vlan_interfaces.json\" - - port_indices_file=\"/tmp/port_indices.json\" + - ports_file=\"/tmp/ports.json\" - dut_mac='{{ ansible_Ethernet0['macaddress'] }}' - default_ip_range='192.168.0.0/16' + - vlan_ip_range=\"{{ minigraph_vlan_interfaces[0]['subnet'] }}\" always: - name: Remove existing ip from ptf host script: roles/test/files/helpers/remove_ip.sh delegate_to: "{{ ptf_host }}" - diff --git a/ansible/roles/test/tasks/fib.yml b/ansible/roles/test/tasks/fib.yml index f14dbd604a4..bf44588234c 100644 --- a/ansible/roles/test/tasks/fib.yml +++ b/ansible/roles/test/tasks/fib.yml @@ -19,14 +19,22 @@ set_fact: props="{{configuration_properties['common']}}" when: testbed_type in ['t0'] +- name: Expand ToR properties into props + set_fact: props_tor="{{configuration_properties['tor']}}" + when: testbed_type in ['t1', 't1-lag'] + - name: Gathering minigraph facts about the device minigraph_facts: host={{ inventory_hostname }} connection: local # Generate route file - name: Generate route-port map information - template: src=fib.j2 - dest=/tmp/route_info.txt + template: src=roles/test/templates/fib.j2 + dest=/tmp/fib_info.txt + connection: local + +- name: copy the fib_info to ptf container + copy: src=/tmp/fib_info.txt dest=/root delegate_to: "{{ptf_host}}" - debug : msg="Start FIB Test" @@ -35,12 +43,23 @@ copy: src=roles/test/files/ptftests dest=/root delegate_to: "{{ ptf_host }}" -- name: "Running the test" - shell: ptf --test-dir ptftests fib_test.FibTest --platform remote -t "testbed_type='{{testbed_type}}';router_mac='{{ansible_Ethernet0['macaddress']}}';route_info='/tmp/route_info.txt'" - args: - chdir: /root - delegate_to: "{{ ptf_host }}" - register: out +- set_fact: ipv4=true + when: ipv4 is not defined + +- set_fact: ipv6=true + when: ipv6 is not defined -- debug: var=out.stdout_lines - when: out.rc != 0 +- name: "Start PTF runner" + include: ptf_runner.yml + vars: + ptf_test_name: FIB test + ptf_test_dir: ptftests + ptf_test_path: fib_test.FibTest + ptf_platform: remote + ptf_test_params: + - testbed_type='{{testbed_type}}' + - router_mac='{{ansible_Ethernet0['macaddress']}}' + - fib_info='/root/fib_info.txt' + - ipv4={{ipv4}} + - ipv6={{ipv6}} + ptf_extra_options: "--relax --log-dir /tmp/" diff --git a/ansible/roles/test/tasks/interface.yml b/ansible/roles/test/tasks/interface.yml index c6b56e6a05d..85c557e6934 100644 --- a/ansible/roles/test/tasks/interface.yml +++ b/ansible/roles/test/tasks/interface.yml @@ -3,5 +3,12 @@ - name: Verify interfaces are up correctly assert: { that: "'{{ ansible_interface_facts[item]['active'] }}' == 'True'" } - with_items: minigraph_interfaces | map(attribute='alias') | list + with_items: "{{ minigraph_ports }}" +- name: Verify port channel interfaces are up correctly + assert: { that: "'{{ ansible_interface_facts[item]['active'] }}' == 'True'" } + with_items: "{{ minigraph_portchannels.keys() }}" + +- name: Verify VLAN interfaces are up correctly + assert: { that: "'{{ ansible_interface_facts[item]['active'] }}' == 'True'" } + with_items: "{{ minigraph_vlans.keys() }}" diff --git a/ansible/roles/test/tasks/lag.yml b/ansible/roles/test/tasks/lag.yml index 64073697300..986dd53569f 100644 --- a/ansible/roles/test/tasks/lag.yml +++ b/ansible/roles/test/tasks/lag.yml @@ -74,9 +74,4 @@ always: - include: roles/test/files/tools/loganalyzer/loganalyzer_analyze.yml - # Output content of result files to ansible console - - shell: cat {{ test_out_dir }}/* - register: out - - debug: var=out.stdout_lines - - - include: roles/test/files/tools/loganalyzer/loganalyzer_end.yml \ No newline at end of file + - include: roles/test/files/tools/loganalyzer/loganalyzer_end.yml diff --git a/ansible/roles/test/tasks/link_flap.yml b/ansible/roles/test/tasks/link_flap.yml index 808e1ca3e6b..69ad611761b 100644 --- a/ansible/roles/test/tasks/link_flap.yml +++ b/ansible/roles/test/tasks/link_flap.yml @@ -1,15 +1,14 @@ -# Shuotian Cheng -# -# This test is part of sswsyncd functionality tests. -# -# In this test, I try to iteratively shutdown and bring up physical interface -# from the DUT spine neighbor side by controlling the underlay fan-out switch. -# Then, I check the neighbor table to ensure certian entries are updated -# according to the certain link flappings. +# This is link flap test. In this test, all DUT's neighbor interfaces are +# flapped. During each flap, the DUT's interface is verified to see if it +# is updated to the correct up/down state. -- name: Gathering minigraph facts about the device - minigraph_facts: host={{ inventory_hostname }} +- name: Gathering lab graph facts about the device + conn_graph_facts: host={{ inventory_hostname }} connection: local + tags: always -- include: link_entry_flap.yml - with_items: "{{ minigraph_interfaces }}" +- set_fact: + neighbors: "{{device_conn}}" + +- include: link_flap/link_flap_helper.yml + with_items: "{{ device_conn.keys() }}" diff --git a/ansible/roles/test/tasks/link_flap/link_flap_helper.yml b/ansible/roles/test/tasks/link_flap/link_flap_helper.yml new file mode 100644 index 00000000000..b59f54be013 --- /dev/null +++ b/ansible/roles/test/tasks/link_flap/link_flap_helper.yml @@ -0,0 +1,62 @@ +# This is the link_flap.yml helper playbook. link_flap.yml passes the interface +# to this playbook and in this playbook the neighbor of this interface is +# flapped. + +- block: + - set_fact: + interface: "{{item}}" + + - debug: msg={{interface}} + + - set_fact: + peer_device: "{{neighbors[interface]['peerdevice']}}" + neighbor_interface: "{{neighbors[interface]['peerport']}}" + + - conn_graph_facts: host={{ peer_device }} + connection: local + + - set_fact: + peer_host: "{{device_info['mgmtip']}}" + peer_hwsku: "{{device_info['HwSku']}}" + + - set_fact: + intfs_to_exclude: "{{interface}}" + + - name: Shut down neighbor interface {{neighbor_interface}} on {{peer_host}} + action: apswitch template=neighbor_interface_shut_single.j2 + args: + host: "{{peer_host}}" + login: "{{switch_login[hwsku_map[peer_hwsku]]}}" + connection: switch + + - pause: + seconds: 20 + + - interface_facts: + + - name: Verify interfaces are up correctly + assert: { that: "'{{ ansible_interface_facts[item]['active'] }}' == 'True'" } + with_items: "{{ minigraph_ports }}" + when: item != "{{ intfs_to_exclude }}" + + - name: Verify {{intfs_to_exclude}} is down correctly + assert: { that: "'{{ ansible_interface_facts[item]['active'] }}' == 'False'" } + with_items: "{{ minigraph_ports }}" + when: item == "{{ intfs_to_exclude }}" + + always: + - name: Bring up neighbor interface {{neighbor_interface}} on {{peer_host}} + action: apswitch template=neighbor_interface_no_shut_single.j2 + args: + host: "{{peer_host}}" + login: "{{switch_login[hwsku_map[peer_hwsku]]}}" + connection: switch + + - pause: + seconds: 20 + + - interface_facts: + + - name: Verify all interfaces are up + assert: { that: "'{{ ansible_interface_facts[item]['active'] }}' == 'True'" } + with_items: "{{ minigraph_ports }}" diff --git a/ansible/roles/test/tasks/lldp.yml b/ansible/roles/test/tasks/lldp.yml index c0c30a53f61..2fa65c56a67 100644 --- a/ansible/roles/test/tasks/lldp.yml +++ b/ansible/roles/test/tasks/lldp.yml @@ -19,17 +19,13 @@ - name: Verify LLDP information is available on most interfaces assert: { that: "{{ lldp|length }} > {{ minigraph_neighbors|length * 0.8 }}"} -- name: Read port alias mapping - set_fact: - alias_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_map.json') | from_json }}" - - name: Compare the lldp neighbors name with minigraph neigbhors name (exclude the management port) - assert: { that: "'{{ lldp[item]['chassis']['name'] }}' == '{{ minigraph_neighbors[alias_map[item]]['name'] }}'" } + assert: { that: "'{{ lldp[item]['chassis']['name'] }}' == '{{ minigraph_neighbors[item]['name'] }}'" } with_items: "{{ lldp.keys() }}" when: item != "eth0" - name: Compare the lldp neighbors interface with minigraph neigbhor interface (exclude the management port) - assert: { that: "'{{ lldp[item]['port']['ifname'] }}' == '{{ minigraph_neighbors[alias_map[item]]['port'] }}'" } + assert: { that: "'{{ lldp[item]['port']['ifname'] }}' == '{{ minigraph_neighbors[item]['port'] }}'" } with_items: "{{ lldp.keys() }}" when: item != "eth0" @@ -38,4 +34,3 @@ with_items: "{{ lldp.keys() }}" when: item != "eth0" - diff --git a/ansible/roles/test/tasks/lldp_neighbor.yml b/ansible/roles/test/tasks/lldp_neighbor.yml index 25d6fea587a..87bf48e887d 100644 --- a/ansible/roles/test/tasks/lldp_neighbor.yml +++ b/ansible/roles/test/tasks/lldp_neighbor.yml @@ -20,4 +20,3 @@ - name: verify the dut port description field is published correctly assert: {that: "'{{ ansible_lldp_facts[neighbor_interface]['neighbor_port_desc'] }}' == dut_interface"} - diff --git a/ansible/roles/test/tasks/mem_check.yml b/ansible/roles/test/tasks/mem_check.yml new file mode 100644 index 00000000000..cee41f02369 --- /dev/null +++ b/ansible/roles/test/tasks/mem_check.yml @@ -0,0 +1,19 @@ +- name: Copy mem_check.sh to the DuT + become: true + copy: + src: roles/test/files/mem_check.sh + dest: /tmp/mem_check.sh + mode: 0755 + +- name: Run mem_check.sh + become: true + shell: /tmp/mem_check.sh + register: results + failed_when: results.rc != 0 + +- name: Delete mem_check.sh from the DuT + become: true + file: + state: absent + path: /tmp/mem_check.sh + diff --git a/ansible/roles/test/tasks/ntp.yml b/ansible/roles/test/tasks/ntp.yml index 841bfb5e914..c65b4cba007 100644 --- a/ansible/roles/test/tasks/ntp.yml +++ b/ansible/roles/test/tasks/ntp.yml @@ -1,9 +1,25 @@ +- name: Stop NTP service + become: true + service: + name: ntp + state: stopped + +- name: Force local clock to sync with an NTP clock + become: true + command: ntpd -gq + +- name: Start NTP service + become: true + service: + name: ntp + state: started + - name: Check if NTP is synced become: true shell: ntpstat register: ntpstat_result until: ntpstat_result.rc == 0 - retries: 5 - delay: 2 + retries: 8 + delay: 10 - debug: msg="NTP Status {{ ntpstat_result.stdout }}" diff --git a/ansible/roles/test/tasks/ptf_runner.yml b/ansible/roles/test/tasks/ptf_runner.yml index 0c92798f790..a06d1fce831 100644 --- a/ansible/roles/test/tasks/ptf_runner.yml +++ b/ansible/roles/test/tasks/ptf_runner.yml @@ -39,7 +39,9 @@ when: ptf_host is not defined - name: "PTF Test - {{ ptf_test_name }}" - shell: ptf --test-dir {{ ptf_test_dir }} {{ ptf_test_path }} {% if ptf_qlen is defined %} --qlen={{ ptf_qlen }} {% endif %} --platform {{ ptf_platform }} {% if ptf_test_params is defined %} -t "{{ ptf_test_params | default([]) | join(';') }}" {% endif %} {{ ptf_extra_options | default("")}} --disable-ipv6 --disable-vxlan --disable-geneve --disable-erspan --disable-mpls --disable-nvgre 2>&1 + debug: msg="ptf --test-dir {{ ptf_test_dir }} {{ ptf_test_path }} {% if ptf_qlen is defined %} --qlen={{ ptf_qlen }} {% endif %} --platform {{ ptf_platform }} {% if ptf_test_params is defined %} -t \"{{ ptf_test_params | default([]) | join(';') }}\" {% endif %} {{ ptf_extra_options | default(\"\")}} --disable-vxlan --disable-geneve --disable-erspan --disable-mpls --disable-nvgre 2>&1" + +- shell: ptf --test-dir {{ ptf_test_dir }} {{ ptf_test_path }} {% if ptf_qlen is defined %} --qlen={{ ptf_qlen }} {% endif %} --platform {{ ptf_platform }} {% if ptf_test_params is defined %} -t "{{ ptf_test_params | default([]) | join(';') }}" {% endif %} {{ ptf_extra_options | default("")}} --disable-vxlan --disable-geneve --disable-erspan --disable-mpls --disable-nvgre 2>&1 args: chdir: /root delegate_to: "{{ ptf_host }}" @@ -50,4 +52,3 @@ - fail: msg="Failed test '{{ ptf_test_name }}'" when: out.rc != 0 - diff --git a/ansible/roles/test/tasks/reboot.yml b/ansible/roles/test/tasks/reboot.yml new file mode 100644 index 00000000000..8134f92134f --- /dev/null +++ b/ansible/roles/test/tasks/reboot.yml @@ -0,0 +1,35 @@ +- name: reboot + become: true + shell: sleep 2 && shutdown -r now "Reboot test." + async: 1 + poll: 0 + ignore_errors: true + +- name: pause for 1 minute before check + pause: minutes=1 + +- name: Wait for switch to come back + local_action: + wait_for host={{ ansible_host }} + port=22 + state=started + delay=10 + timeout=180 + search_regex="OpenSSH_[\w\.]+ Debian" + become: false + changed_when: false + +- name: wait again, processes and interfaces are not availabe right away + pause: seconds=120 + +- name: sanity check to pass + include: base_sanity.yml + +- name: Gathering minigraph facts about the device + minigraph_facts: host={{ inventory_hostname }} + connection: local + become: no + when: minigraph_interfaces is not defined + +- include: interface.yml + diff --git a/ansible/roles/test/tasks/snmp/interfaces.yml b/ansible/roles/test/tasks/snmp/interfaces.yml index 93f0a9e518e..a77901fd7a7 100644 --- a/ansible/roles/test/tasks/snmp/interfaces.yml +++ b/ansible/roles/test/tasks/snmp/interfaces.yml @@ -5,27 +5,29 @@ - set_fact: snmp_intf: [] - -- set_fact: mg_intf: [] - name: Create snmp interfaces list set_fact: - snmp_intf: "{{snmp_intf + [item.value.name] }}" - with_dict: snmp_interfaces + snmp_intf: "{{ snmp_intf + [item.value.name] }}" + with_dict: "{{ snmp_interfaces }}" when: "{{item.value.name is defined}}" - name: Create minigraph interfaces list set_fact: - mg_intf: "{{mg_intf + [item.name] }}" - with_items: minigraph_interfaces - when: "{{item.name is defined}}" + mg_intf: "{{ mg_intf + [item.value.alias] }}" + with_dict: "{{ minigraph_ports }}" +- name: Add port channel interfaces into minigraph interfaces list + set_fact: + mg_intf: "{{ mg_intf + [item.key] }}" + with_dict: "{{ minigraph_portchannels }}" + +- debug: var=minigraph_map_sonic_to_ngs - debug: var=snmp_intf - debug: var=mg_intf - name: Check for missing interfaces in SNMP - fail: msg="Minigraph interface {{item}} not in SNMP interfaces" - when: "{{item not in snmp_intf}}" - with_items: mg_intf - + fail: msg="Minigraph interface {{ minigraph_map_sonic_to_ngs[item] if item in minigraph_map_sonic_to_ngs else item }} not in SNMP interfaces" + when: "{{ (item in minigraph_map_sonic_to_ngs and minigraph_map_sonic_to_ngs[item] not in snmp_intf) or (item not in minigraph_map_sonic_to_ngs and item not in snmp_intf) }}" + with_items: "{{ mg_intf }}" diff --git a/ansible/roles/test/tasks/sonic.yml b/ansible/roles/test/tasks/sonic.yml index 65a14f4bb40..a6ae3179532 100644 --- a/ansible/roles/test/tasks/sonic.yml +++ b/ansible/roles/test/tasks/sonic.yml @@ -4,6 +4,13 @@ become: no tags: always +### When calling the following tests, you need to provide a command line parameter +### specifying which PTF docker image host to test against. For example, +### -e "ptf_host=10.0.0.200" +- fail: msg="Please set ptf_host variable" + when: ptf_host is not defined + tags: arp,dhcp_relay + - name: Verify interfaces are up include: interface.yml tags: always @@ -64,32 +71,26 @@ include: link_flap.yml tags: link_flap -### when calling this ARP test, please add command line of which PTF docker image host to test against -### -e "ptf_host=10.0.0.200" -- fail: msg="Please set ptf_host variable" - when: ptf_host is not defined - tags: arp - - name: Test kernel ARP behavior include: arpall.yml tags: arp - - name: Decap test include: decap.yml tags: decap +- name: Test sensors + include: sensors_check.yml + tags: sensors + ### When calling this FIB test, please add command line of what testbed_type and which PTF docker to test against ### -e "testbed_type=t1-lag ptf_host=10.0.0.200" - name: Fib test include: fib.yml tags: fib -- name: Acl test setup on testbed +- name: Acl test include: acltb.yml - -- name: Test ACL - include: acl.yml tags: acl - name: Test Everflow @@ -99,6 +100,14 @@ - name: Test Everflow on testbed include: everflow_testbed.yml -- name: Test LAG. +- name: Test LAG include: lagall.yml tags: lag + +- name: Memory check + include: mem_check.yml + tags: mem_check + +- name: Test reboot + include: reboot.yml + tags: reboot diff --git a/ansible/roles/test/tasks/syslog.yml b/ansible/roles/test/tasks/syslog.yml index 13fc97a6209..d83bbe06280 100644 --- a/ansible/roles/test/tasks/syslog.yml +++ b/ansible/roles/test/tasks/syslog.yml @@ -31,80 +31,89 @@ local_srcip: "{{ local_facts.ansible_facts.ansible_eth0.ipv4.address }}" original_syslog_servers: "{{ syslog_servers }}" syslog_port: "{{ 65535 | random(start=65000) }}" + test_message: "Basic Test Message" - debug: var=local_srcip -# TODO: (johnar) rsyslog template needs to be changed to allow variable port. Static the config for now... -# Reconfigure syslog on the DUT to point at this remote host -# set_fact: -# syslog_servers: -# - "{{ local_srcip }}" - -#- name: Reconfigure Rsyslog for Testing -# become: true -# template: src=../../acs/templates/rsyslog.conf.j2 -# dest=/etc/rsyslog.conf - - name: Add Rsyslog destination for testing become: true - shell: 'echo "*.* @{{ local_srcip }}:{{ syslog_port }}" >> /etc/rsyslog.conf' + lineinfile: + line: "*.* @{{ local_srcip }}:{{ syslog_port }}" + dest: /etc/rsyslog.conf + state: present - name: Restart Syslog Daemon become: true service: name=rsyslog state=restarted -# Start Syslog Server +# Start local ryslog Server -- name: Start Syslog Server on ansible localhost - syslog_server: timeout=10 port="{{ syslog_port }}" host="{{ local_srcip }}" - async: 60 - poll: 0 - register: syslog_sleeper +- name: Load imudp module in local syslog connection: local - become: no + become: true + lineinfile: + line: "module(load=\"imudp\")" + dest: /etc/rsyslog.conf + state: present -- name: Wait a little bit for service to start - wait_for: timeout=2 +- name: Remove imudp ports + connection: local + become: true + lineinfile: + regexp: "input\\(type=\"imudp\" port=\"\\d+\"\\)" + dest: /etc/rsyslog.conf + state: absent -# SSH to device and generate a syslog -- name: Send test syslog - become: yes - command: logger --priority INFO Basic Test Message +- name: Add imudp port {{ syslog_port }} + connection: local + become: true + lineinfile: + line: "input(type=\"imudp\" port=\"{{ syslog_port }}\")" + dest: /etc/rsyslog.conf + state: present -#- debug: var=syslog_sleeper +- name: Stop Syslog Daemon + connection: local + become: true + shell: killall rsyslogd + ignore_errors: true -# Retreive syslogs -- name: Retreive syslog messages - async_status: jid="{{ syslog_sleeper.ansible_job_id }}" - register: job_result - until: job_result.finished - retries: 30 - delay: 1 +- name: Remove local /var/log/syslog + become: true connection: local + file: + path: /var/log/syslog + state: absent -- debug: msg="{{ syslog_messages }}" +- name: Start Syslog Daemon + connection: local + become: true + service: name=rsyslog state=started -# Reconfigure Rsyslog to to original state +- name: Wait a little bit for service to start + wait_for: timeout=2 -- set_fact: - syslog_servers: "{{ original_syslog_servers }}" +# SSH to device and generate a syslog +- name: Send test syslog + become: yes + command: logger --priority INFO {{ test_message }} -- name: Reconfigure Rsyslog to original state - template: src=roles/sonic-common/templates/rsyslog.conf.j2 - dest=/etc/rsyslog.conf +- name: Restore original /etc/rsyslog.conf become: true + lineinfile: + regexp: "\\*\\.\\* @{{ local_srcip }}:{{ syslog_port }}" + dest: /etc/rsyslog.conf + state: absent - name: Restart Syslog Daemon become: true service: name=rsyslog state=restarted - # Check Messages - name: Check syslog messages for the test message - set_fact: - found1: "true" - when: "{{ item | search('Basic Test Message') }}" - with_items: "{{ syslog_messages }}" + connection: local + become: true + shell: grep {{ inventory_hostname }} /var/log/syslog | grep "{{ test_message }}" | grep -v ansible + register: grep_result -- fail: msg='Unable to find test syslog "Basic Test Message"' - when: found1 is not defined +- debug: var=grep_result diff --git a/ansible/roles/test/templates/acltb.j2 b/ansible/roles/test/templates/acltb.j2 index e30d899d605..8a4b65660bc 100644 --- a/ansible/roles/test/templates/acltb.j2 +++ b/ansible/roles/test/templates/acltb.j2 @@ -1,8 +1,8 @@ {# tor ports #} -{% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T0" in v.name %}{{ '%d' % (alias_reverse_map[ifname]|replace("Ethernet","")|int / 4)}},{% endif %}{% endfor %} +{% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T0" in v.name %}{{ '%d' % minigraph_port_indices[ifname] }},{% endif %}{% endfor %} {# spine ports #} -{% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T2" in v.name %}{{ '%d' % (alias_reverse_map[ifname]|replace("Ethernet","")|int / 4)}},{% endif %}{% endfor %} +{% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T2" in v.name %}{{ '%d' % minigraph_port_indices[ifname] }},{% endif %}{% endfor %} 192.168.0.0 192.168.0.16 diff --git a/ansible/roles/test/templates/bgp_neighbor_noshut.j2 b/ansible/roles/test/templates/bgp_neighbor_noshut.j2 index fef0f8c4b29..fe8a98b7852 100644 --- a/ansible/roles/test/templates/bgp_neighbor_noshut.j2 +++ b/ansible/roles/test/templates/bgp_neighbor_noshut.j2 @@ -1,7 +1,7 @@ configure router bgp {{ asn }} {% if "Arista" in hwsku %} -no neighbor {{ peer_addr }} shutdown +default neighbor {{ peer_addr }} shutdown {% else %} neighbor {{ peer_addr }} no shutdown diff --git a/ansible/roles/test/templates/fib.j2 b/ansible/roles/test/templates/fib.j2 index 7d000fe118c..ec9acc35c64 100644 --- a/ansible/roles/test/templates/fib.j2 +++ b/ansible/roles/test/templates/fib.j2 @@ -1,28 +1,56 @@ -{% if testbed_type == 't1' or testbed_type == 't1-lag' %} +{# defualt route#} +{% if testbed_type == 't1' %} +0.0.0.0/0 {% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T2" in v.name %}{{ '[%d]' % minigraph_port_indices[ifname]}}{% if not loop.last %} {% endif %}{% endif %}{% endfor %} +{% elif testbed_type == 't0' or testbed_type == 't1-lag' %} +0.0.0.0/0 {% for portchannel, v in minigraph_portchannels.iteritems() %} +[{% for member in v.members %}{{ '%d' % minigraph_port_indices[member]}}{% if not loop.last %} {% endif %}{% endfor %}]{% if not loop.last %} {% endif %}{% endfor %} +{% endif %} + +{#routes to uplink#} {% for podset in range(0, props.podset_number) %} {% for tor in range(0, props.tor_number) %} {% for subnet in range(0, props.tor_subnet_number) %} -192.168.{{ podset }}.{{ tor * 16 + subnet }} -20C0:A8{{ '%02X' % podset }}:0:{{ '%02X' % (tor * 16 + subnet)}}:: -{% endfor %} -{% endfor %} -{% endfor %} +{% if testbed_type == 't1' %} +192.168.{{ podset }}.{{ tor * 16 + subnet }}/32 {% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T2" in v.name %}{{ '[%d]' % minigraph_port_indices[ifname]}}{% if not loop.last %} {% endif %}{% endif %}{% endfor %} + +20C0:A8{{ '%02X' % podset }}:0:{{ '%02X' % (tor * 16 + subnet)}}::/64 {% for ifname, v in minigraph_neighbors.iteritems() %}{% if "T2" in v.name %}{{ '[%d]' % minigraph_port_indices[ifname]}}{% if not loop.last %} {% endif %}{% endif %}{% endfor %} + +{% elif testbed_type == 't1-lag' %} +192.168.{{ podset }}.{{ tor * 16 + subnet }}/32 {% for portchannel, v in minigraph_portchannels.iteritems() %} +[{% for member in v.members %}{{ '%d' % minigraph_port_indices[member]}}{% if not loop.last %} {% endif %}{% endfor %}]{% if not loop.last %} {% endif %}{% endfor %} + +20C0:A8{{ '%02X' % podset }}:0:{{ '%02X' % (tor * 16 + subnet)}}::/64 {% for portchannel, v in minigraph_portchannels.iteritems() %} +[{% for member in v.members %}{{ '%d' % minigraph_port_indices[member]}}{% if not loop.last %} {% endif %}{% endfor %}]{% if not loop.last %} {% endif %}{% endfor %} + {% elif testbed_type == 't0' %} -{% for podset in range(0, props.podset_number) %} -{% for tor in range(0, props.tor_number) %} -{% for subnet in range(0, props.tor_subnet_number) %} {% set suffix = ( (podset * props.tor_number * props.max_tor_subnet_number * props.tor_subnet_size) + (tor * props.max_tor_subnet_number * props.tor_subnet_size) + (subnet * props.tor_subnet_size) ) %} {% set octet2 = (168 + ((suffix // (256 ** 2))) % 256) %} {% set octet3 = ((suffix // 256) % 256) %} {% set octet4 = (suffix % 256) %} +{% set prefixlen_v4 = (32 - ((props.tor_subnet_size | log(2))) | int) %} {# Skip 192.168.0.0 as it is in Vlan1000 subnet #} {% if octet2 != 168 and octet3 != 0 and octet4 != 0 %} -192.{{ octet2 }}.{{ octet3 }}.{{ octet4 }} -20C0:{{ '%02X%02X' % (octet2, octet3) }}:0:{{ '%02X' % octet4 }}:: +192.{{ octet2 }}.{{ octet3 }}.{{ octet4 }}/{{ prefixlen_v4 }} {% for portchannel, v in minigraph_portchannels.iteritems() %}[{% for member in v.members %}{{ '%d' % minigraph_port_indices[member]}}{% if not loop.last %} {% endif %}{% endfor %}]{% if not loop.last %} {% endif %}{% endfor %} + +20C0:{{ '%02X%02X' % (octet2, octet3) }}:0:{{ '%02X' % octet4 }}::/64 {% for portchannel, v in minigraph_portchannels.iteritems() %}[{% for member in v.members %}{{ '%d' % minigraph_port_indices[member]}}{% if not loop.last %} {% endif %}{% endfor %}]{% if not loop.last %} {% endif %}{% endfor %} + +{% endif %} {% endif %} {% endfor %} {% endfor %} {% endfor %} +{# routes to downlink #} +{% if testbed_type == 't1' or testbed_type == 't1-lag' %} +{% for ifname, v in minigraph_neighbors.iteritems() %} +{% if "T0" in v.name %} +{% for subnet in range(0, props_tor.tor_subnet_number) %} +172.16.{{ v.name|replace("ARISTA", "")|replace("T0", "")|int }}.{{ subnet }}/32 {{ '[%d]' % minigraph_port_indices[ifname]}}{% if not loop.last %} {% endif %} + +20AC:10{{ '%02X' % v.name|replace("ARISTA", "")|replace("T0", "")|int }}:0:{{ '%02X' % subnet }}::/64 {{ '[%d] ' % minigraph_port_indices[ifname]}}{% if not loop.last %} {% endif %} + +{% endfor %} +{% endif %} +{% endfor %} {% endif %} diff --git a/ansible/roles/test/templates/neighbor_interface_no_shut_single.j2 b/ansible/roles/test/templates/neighbor_interface_no_shut_single.j2 index 1ce6063c59a..f704f975cb8 100644 --- a/ansible/roles/test/templates/neighbor_interface_no_shut_single.j2 +++ b/ansible/roles/test/templates/neighbor_interface_no_shut_single.j2 @@ -1,5 +1,5 @@ configure - interface {{ minigraph_neighbors[item].port }} + interface {{ neighbor_interface }} no shutdown exit exit diff --git a/ansible/roles/test/templates/neighbor_interface_shut_single.j2 b/ansible/roles/test/templates/neighbor_interface_shut_single.j2 new file mode 100644 index 00000000000..3c8a2e8e38e --- /dev/null +++ b/ansible/roles/test/templates/neighbor_interface_shut_single.j2 @@ -0,0 +1,6 @@ +configure + interface {{ neighbor_interface }} + shutdown + exit +exit +exit diff --git a/ansible/roles/vm_set/tasks/start.yml b/ansible/roles/vm_set/tasks/start.yml index 071ba83f406..c5ea4c37712 100644 --- a/ansible/roles/vm_set/tasks/start.yml +++ b/ansible/roles/vm_set/tasks/start.yml @@ -1,4 +1,4 @@ -- name: Set sysctl parameters for testbed +- name: Set sysctl bridge parameters for testbed sysctl: name: "{{ item }}" value: 0 @@ -8,6 +8,12 @@ - net.bridge.bridge-nf-call-ip6tables - net.bridge.bridge-nf-call-iptables +- name: Set sysctl RCVBUF parameter for testbed + sysctl: + name: "net.core.rmem_max" + value: 509430500 + sysctl_set: yes + - name: Create directory for vm images and vm disks file: path={{ item }} state=directory mode=0755 recurse=yes with_items: @@ -73,4 +79,3 @@ port1_tap: "{{ vm_name }}-back" with_items: "{{ VM_hosts }}" -