Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[everflow_testbed] extend test to cover egress mirroring #1094

Merged
merged 6 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions ansible/library/switch_capabilities_facts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/python

import swsssdk

DOCUMENTATION = '''
module: switch_capability_facts
version_added: "1.0"
author: Stepan Blyschak (stepanb@mellanox.com)
short_description: Retrieve switch capability information
'''

EXAMPLES = '''
- name: Get switch capability facts
switch_capability_facts:
'''


class SwitchCapabilityModule(object):
def __init__(self):
self.module = AnsibleModule(
argument_spec=dict(
),
supports_check_mode=True)

self.out = None
self.facts = {}

return

def run(self):
"""
Main method of the class
"""
self.facts['switch_capabilities'] = {}

conn = swsssdk.SonicV2Connector(host='127.0.0.1')
conn.connect(conn.STATE_DB)
keys = conn.keys(conn.STATE_DB, 'SWITCH_CAPABILITY|*')

for key in keys:
capab = conn.get_all(conn.STATE_DB, key)
self.facts['switch_capabilities'][key.split('|')[-1]] = capab

self.module.exit_json(ansible_facts=self.facts)


def main():
SwitchCapabilityModule().run()


from ansible.module_utils.basic import *
if __name__ == "__main__":
main()
23 changes: 19 additions & 4 deletions ansible/roles/test/files/acstests/everflow_policer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def setUp(self):
self.hwsku = self.test_params['hwsku']
self.asic_type = self.test_params['asic_type']
self.router_mac = self.test_params['router_mac']
self.mirror_stage = self.test_params['mirror_stage']
self.session_src_ip = "1.1.1.1"
self.session_dst_ip = "2.2.2.2"
self.session_ttl = 1
Expand Down Expand Up @@ -106,7 +107,15 @@ def checkMirroredFlow(self):
Mellanox crafts the GRE packets with extra information:
That is: 22 bytes extra information after the GRE header
"""
payload = self.base_pkt
payload = self.base_pkt.copy()
payload_mask = Mask(payload)

if self.mirror_stage == "egress":
payload['Ethernet'].src = self.router_mac
payload['IP'].ttl -= 1
payload_mask.set_do_not_care_scapy(scapy.Ether, "dst")
payload_mask.set_do_not_care_scapy(scapy.IP, "chksum")

if self.asic_type in ["mellanox"]:
import binascii
payload = binascii.unhexlify("0"*44) + str(payload) # Add the padding
Expand All @@ -130,17 +139,23 @@ def checkMirroredFlow(self):
masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst")
masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "flags")
masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum")
masked_exp_pkt.set_do_not_care(38*8, len(payload)*8) # don't match payload, payload will be matched by match_payload(pkt)

if self.asic_type in ["mellanox"]:
masked_exp_pkt.set_do_not_care(304, 176) # Mask the Mellanox specific inner header
def match_payload(pkt):
pkt = scapy.Ether(pkt).load
if self.asic_type in ["mellanox"]:
pkt = pkt[22:] # Mask the Mellanox specific inner header
pkt = scapy.Ether(pkt)

return dataplane.match_exp_pkt(payload_mask, pkt)

self.dataplane.flush()

count = 0
for i in range(0,self.NUM_OF_TOTAL_PACKETS):
testutils.send_packet(self, self.src_port, self.base_pkt)
(rcv_device, rcv_port, rcv_pkt, pkt_time) = testutils.dp_poll(self, timeout=0.1, exp_pkt=masked_exp_pkt)
if rcv_pkt is not None:
if rcv_pkt is not None and match_payload(rcv_pkt):
count += 1
elif count == 0:
print "The first mirrored packet is not recieved"
Expand Down
16 changes: 15 additions & 1 deletion ansible/roles/test/files/acstests/everflow_tb_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ def setUp(self):
self.src_port = int(float(self.test_params['src_port']))
self.dst_ports = [int(float(p)) for p in self.test_params['dst_ports'].split(",") if p]
self.expected_dst_mac = self.test_params.get('expected_dst_mac', None)
self.expect_received = self.test_params.get('expect_received', True)
self.acl_stage = self.test_params.get('acl_stage', 'ingress')
self.mirror_stage = self.test_params.get('mirror_stage', 'ingress')

testutils.add_filter(self.gre_type_filter)

Expand Down Expand Up @@ -106,7 +109,7 @@ def receivePacketOnPorts(self, ports=[], device_number=0):
return (match_index, rcv_pkt, received)


def runSendReceiveTest(self, pkt2send, src_port, destination_ports):
def sendReceive(self, pkt2send, src_port, destination_ports):
"""
@summary Send packet and verify it is received/not received on the expected ports
"""
Expand Down Expand Up @@ -149,7 +152,12 @@ def runSendReceiveTest(self, pkt2send, src_port, destination_ports):

inner_pkt = scapy.Ether(payload)

if self.mirror_stage == 'egress':
pkt2send['IP'].ttl -= 1 # expect mirrored packet on egress has TTL decremented

masked_inner_pkt = Mask(inner_pkt)
masked_inner_pkt.set_do_not_care_scapy(scapy.Ether, "dst")
masked_inner_pkt.set_do_not_care_scapy(scapy.Ether, "src")
if scapy.IP in inner_pkt:
masked_inner_pkt.set_do_not_care_scapy(scapy.IP, "chksum")

Expand All @@ -158,6 +166,12 @@ def runSendReceiveTest(self, pkt2send, src_port, destination_ports):

return dataplane.match_exp_pkt(masked_inner_pkt, pkt2send)

def runSendReceiveTest(self, pkt, src_port, dst_ports):
if self.expect_received:
return self.sendReceive(pkt, src_port, dst_ports)
else:
return not self.sendReceive(pkt, src_port, dst_ports)


@reportResults("Verify SRC IP match")
def verifySrcIp(self):
Expand Down
38 changes: 24 additions & 14 deletions ansible/roles/test/tasks/everflow_testbed.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
- name: Apply Everflow configuration.
include: "roles/test/tasks/everflow_testbed/apply_config.yml"
tags: everflow_tb_configure
- name: Get switch capabilities
include: "roles/test/tasks/everflow_testbed/get_capabilities_info.yml"

- name: Run Everflow tests.
include: "roles/test/tasks/everflow_testbed/run_test.yml"
- name: Get general port information
include: "roles/test/tasks/everflow_testbed/get_general_port_info.yml"

- include: "roles/test/tasks/everflow_testbed/everflow_main.yml"
vars:
mirror_stage: "ingress"
acl_stage: "ingress"
when: test_ingress_mirror_on_ingress_acl == true

- include: "roles/test/tasks/everflow_testbed/everflow_main.yml"
vars:
dst_port_type: "tor"
tags: everflow_tb_test
mirror_stage: "egress"
acl_stage: "ingress"
when: test_egress_mirror_on_ingress_acl == true

- name: Run Everflow tests.
include: "roles/test/tasks/everflow_testbed/run_test.yml"
- include: "roles/test/tasks/everflow_testbed/everflow_main.yml"
vars:
dst_port_type: "spine"
tags: everflow_tb_test
mirror_stage: "ingress"
acl_stage: "egress"
when: test_ingress_mirror_on_egress_acl == true

- name: Clear Everflow configuration.
include: "roles/test/tasks/everflow_testbed/del_config.yml"
tags: everflow_tb_cleanup
- include: "roles/test/tasks/everflow_testbed/everflow_main.yml"
vars:
mirror_stage: "egress"
acl_stage: "egress"
when: test_egress_mirror_on_egress_acl == true
51 changes: 48 additions & 3 deletions ansible/roles/test/tasks/everflow_testbed/apply_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,59 @@
tests_location: roles/test/tasks/everflow_testbed
testname: apply_config

- name: Create running directory
command: "mkdir -p {{ run_dir }}"

- name: Get session info.
include: roles/test/tasks/everflow_testbed/get_session_info.yml

- name: Copy ACL rules configuration file.
copy: src={{ tests_location }}/{{ testname}}/acl_rule_persistent.json dest={{ run_dir }}/
- name: Set Everflow table name
set_fact:
acl_table_name: "EVERFLOW"

- block:
- name: Init variables
set_fact:
acl_table_name: "EVERFLOW_EGRESS"
acl_table_ports: "{{ everflow_table_ports }}"
acl_table_stage: "{{ acl_stage }}"
acl_table_type: "MIRROR"

- name: Remove default SONiC Everflow table (since SONiC allows only one mirror table)
command: "config acl remove table EVERFLOW"
become: yes

- name: Set a flag that need recover config from config_db.json
set_fact:
recover_from_cfgdb_file: True

- name: Generate config for egress Everflow table
template:
src: "roles/test/templates/acltb_table.j2"
dest: "{{ run_dir }}/everflow_egress_table.json"

- name: Create egress Everflow table
command: "sonic-cfggen -j {{ run_dir }}/everflow_egress_table.json --write-to-db"
become: yes
when: acl_stage == "egress"

- name: Copy ACL rules configuration file
template:
src={{ tests_location }}/{{ testname}}/acl_rule_persistent.json.j2
dest={{ run_dir }}/acl_rule_persistent.json

- command: "config mirror_session add {{session_name}} {{session_src_ip}} {{session_dst_ip}} {{session_dscp}} {{session_ttl}} {{session_gre}} {{session_queue}}"
become: yes

- command: "acl-loader update full {{ run_dir }}/acl_rule_persistent.json --session_name={{ session_name }}"
- name: Set acl-loader command
set_fact:
load_rule_cmd: "acl-loader update full {{ run_dir }}/acl_rule_persistent.json --session_name={{ session_name }}"

- name: Append stage parameter if needed
set_fact:
load_rule_cmd: "{{ load_rule_cmd }} --mirror_stage={{ mirror_stage }}"
when: mirror_stage == "egress"

- name: Load ACL mirror rules
command: "{{ load_rule_cmd }}"
become: yes
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"acl": {
"acl-sets": {
"acl-set": {
"everflow": {
"{{ acl_table_name }}": {
"acl-entries": {
"acl-entry": {
"1": {
Expand Down
37 changes: 37 additions & 0 deletions ansible/roles/test/tasks/everflow_testbed/everflow_main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
- fail:
msg: "Mirror stage is not defined or invalid"
when: mirror_stage is not defined or mirror_stage not in ['ingress', 'egress']

- fail:
msg: "ACL stage is not defined or invalid"
when: acl_stage is not defined or acl_stage not in ['ingress', 'egress']

- name: Set flag that recover from config_db.json is needed (default - false)
set_fact:
recover_from_cfgdb_file: False

- name: Apply Everflow configuration.
include: "roles/test/tasks/everflow_testbed/apply_config.yml"
tags: everflow_tb_configure

- name: Run Everflow tests [tor].
include: "roles/test/tasks/everflow_testbed/run_test.yml"
vars:
dst_port_type: "tor"
tags: everflow_tb_test

- name: Run Everflow tests [spine].
include: "roles/test/tasks/everflow_testbed/run_test.yml"
vars:
dst_port_type: "spine"
tags: everflow_tb_test

- name: Clear Everflow configuration.
include: "roles/test/tasks/everflow_testbed/del_config.yml"
tags: everflow_tb_cleanup

- name: Reload config
Copy link
Collaborator

Choose a reason for hiding this comment

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

not sure i fully understand. previously it was mentioned that a variable is kept if this need to be done or not but i dont see this variable is being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This task has a when: recover_from_cfgdb_file condition

include: "roles/test/tasks/common_tasks/reload_config.yml"
vars:
config_source: "config_db"
when: recover_from_cfgdb_file
27 changes: 27 additions & 0 deletions ansible/roles/test/tasks/everflow_testbed/everflow_ptf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
- set_fact:
expect_received: True
when: expect_received is not defined

- name: Send traffic and verify that packets with correct Everflow header are {{ expect_received | ternary('', 'not') }} received on destination port {{ dst_port }}
include: roles/test/tasks/ptf_runner.yml
vars:
ptf_test_name: Everflow Test
ptf_test_dir: acstests
ptf_test_path: everflow_tb_test.EverflowTest
ptf_platform_dir: ptftests
ptf_platform: remote
ptf_test_params:
- asic_type='{{ sonic_asic_type }}'
- hwsku='{{ sonic_hwsku }}'
- router_mac='{{ ansible_Ethernet0['macaddress'] }}'
- src_port='{{ src_port_ptf_id }}'
- dst_ports='{{ dst_port_ptf_id }}'
- session_src_ip='{{ session_src_ip }}'
- session_dst_ip='{{ session_dst_ip }}'
- session_ttl='{{ session_ttl }}'
- session_dscp='{{ session_dscp }}'
- acl_stage='{{ acl_stage }}'
- mirror_stage='{{ mirror_stage }}'
- expect_received={{ expect_received }}
- verbose=True
ptf_extra_options: "--log-file /tmp/everflow_tb_test.EverflowTest.{{lookup('pipe','date +%Y-%m-%d-%H:%M:%S')}}.log"
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
- name: get switch capabilities
switch_capabilities_facts:

- name: initialize variables
set_fact:
test_mirror_v4: False
test_mirror_v6: False
test_ingress_mirror_on_ingress_acl: False
test_ingress_mirror_on_egress_acl: False
test_egress_mirror_on_egress_acl: False
test_egress_mirror_on_ingress_acl: False

- name: set flag if mirroring is supported
set_fact:
test_mirror_v4: True
when: switch_capabilities['switch']['MIRROR'] | lower == 'true'

- name: set flag if V6 mirroring is supported
set_fact:
test_mirror_v6: True
when: switch_capabilities['switch']['MIRRORV6'] | lower == 'true'

- name: set flag if ingress mirroring on ingress ACL is supported
set_fact:
test_ingress_mirror_on_ingress_acl: True
when: "{{ 'MIRROR_INGRESS_ACTION' in switch_capabilities['switch']['ACL_ACTIONS|INGRESS'] }}"

- name: set flag if egress mirroring on ingress ACL is supported
set_fact:
test_egress_mirror_on_ingress_acl: True
when: "{{ 'MIRROR_EGRESS_ACTION' in switch_capabilities['switch']['ACL_ACTIONS|INGRESS'] }}"

- name: set flag if ingress mirroring on egress ACL is supported
set_fact:
test_ingress_mirror_on_egress_acl: True
when: "{{ 'MIRROR_INGRESS_ACTION' in switch_capabilities['switch']['ACL_ACTIONS|EGRESS'] }}"

- name: set flag if egress mirroring on egress ACL is supported
set_fact:
test_egress_mirror_on_egress_acl: True
when: "{{ 'MIRROR_EGRESS_ACTION' in switch_capabilities['switch']['ACL_ACTIONS|EGRESS'] }}"

- debug: var=test_mirror_v4
- debug: var=test_mirror_v6
- debug: var=test_ingress_mirror_on_ingress_acl
- debug: var=test_ingress_mirror_on_egress_acl
- debug: var=test_egress_mirror_on_ingress_acl
- debug: var=test_egress_mirror_on_egress_acl

Loading