-
Notifications
You must be signed in to change notification settings - Fork 771
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Everflow tests implementation (#130)
Add implementation of everflow config and login tests. Everflow testbed test implementation. Add implementation of testcase #1 Resolved route. Everflow testbed test implementation. Add implementation of testcase #2-8.
- Loading branch information
1 parent
98826f6
commit 59f5692
Showing
65 changed files
with
1,692 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
''' | ||
Description: This file contains the Everflow test for SONiC testbed | ||
Implemented according to the https://github.com/Azure/SONiC/wiki/Everflow-test-plan | ||
Usage: Examples of how to use: | ||
ptf --test-dir acstests everflow_tb_test.EverflowTest --platform remote -t 'router_mac="00:02:03:04:05:00";src_port="20";dst_ports="21,22";session_src_ip="1.1.1.1";session_dst_ip="2.2.2.2";session_ttl="64";session_dscp="0";verbose=True' | ||
''' | ||
|
||
|
||
import ptf | ||
import ptf.packet as scapy | ||
import ptf.dataplane as dataplane | ||
import ptf.testutils as testutils | ||
from ptf.base_tests import BaseTest | ||
|
||
|
||
def reportResults(test_name): | ||
''' | ||
@summary Report test result | ||
''' | ||
def testDecorator(func): | ||
def wrapper(*args, **kwargs): | ||
res = func(*args, **kwargs) | ||
print 'Test "%s" %s' % (test_name, "PASSED" if res else "FAILED") | ||
return res | ||
return wrapper | ||
return testDecorator | ||
|
||
|
||
class EverflowTest(BaseTest): | ||
''' | ||
@summary: Everflow tests on testbed topo: t1 or t1-lag | ||
''' | ||
|
||
GRE_PROTOCOL_NUMBER = 47 | ||
PORT_COUNT = 31 # temporary exclude the last port | ||
|
||
|
||
def __init__(self): | ||
''' | ||
@summary: constructor | ||
''' | ||
BaseTest.__init__(self) | ||
self.test_params = testutils.test_params_get() | ||
|
||
|
||
def gre_type_filter(self, pkt_str): | ||
''' | ||
@summaty: Filter GRE packets | ||
''' | ||
try: | ||
pkt = scapy.Ether(pkt_str) | ||
|
||
if scapy.IP not in pkt: | ||
return False | ||
|
||
return pkt[scapy.IP].proto == self.GRE_PROTOCOL_NUMBER | ||
except: | ||
return False | ||
|
||
|
||
def setUp(self): | ||
''' | ||
@summary: Setup for the test | ||
''' | ||
|
||
self.dataplane = ptf.dataplane_instance | ||
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'] | ||
self.session_ttl = int(self.test_params['session_ttl']) | ||
self.session_dscp = int(self.test_params['session_dscp']) | ||
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(",")] | ||
self.expected_dst_mac = self.test_params.get('expected_dst_mac', None) | ||
|
||
testutils.add_filter(self.gre_type_filter) | ||
|
||
self.tests_total = 0 | ||
self.base_pkt = testutils.simple_tcp_packet( | ||
eth_dst = self.router_mac, | ||
eth_src = self.dataplane.get_mac(0, 0), | ||
ip_src = "20.0.0.1", | ||
ip_dst = "30.0.0.1", | ||
tcp_sport = 0x1234, | ||
tcp_dport = 0x50, | ||
ip_ttl = 64 | ||
) | ||
|
||
|
||
def receivePacketOnPorts(self, ports=[], device_number=0): | ||
''' | ||
@summary Receive packet on any of specified ports | ||
''' | ||
received = False | ||
match_index = 0 | ||
(rcv_device, rcv_port, rcv_pkt, pkt_time) = testutils.dp_poll(self, device_number=device_number, timeout=1) | ||
|
||
if rcv_port in ports: | ||
match_index = ports.index(rcv_port) | ||
received = True | ||
|
||
return (match_index, rcv_pkt, received) | ||
|
||
|
||
def runSendReceiveTest(self, pkt2send, src_port, destination_ports): | ||
""" | ||
@summary Send packet and verify it is received/not received on the expected ports | ||
""" | ||
|
||
testutils.send_packet(self, src_port, pkt2send) | ||
(index, rcv_pkt, received) = self.receivePacketOnPorts(destination_ports) | ||
|
||
self.tests_total += 1 | ||
|
||
if not received: | ||
return False | ||
|
||
scapy_pkt = scapy.Ether(rcv_pkt) | ||
|
||
if scapy.IP not in scapy_pkt: | ||
return False | ||
|
||
if self.expected_dst_mac and scapy_pkt.dst != self.expected_dst_mac: | ||
return False | ||
|
||
if scapy_pkt[scapy.IP].src != self.session_src_ip: | ||
return False | ||
|
||
if scapy_pkt[scapy.IP].dst != self.session_dst_ip: | ||
return False | ||
|
||
if scapy_pkt[scapy.IP].ttl != self.session_ttl: | ||
return False | ||
|
||
# TODO: Fanout modifies DSCP. TOS value is olways 0. | ||
#if (scapy_pkt[scapy.IP].tos >> 2) != self.session_dscp: | ||
# return False | ||
|
||
payload = str(scapy_pkt[scapy.GRE].payload)[22:] | ||
inner_pkt = scapy.Ether(payload) | ||
|
||
return dataplane.match_exp_pkt(pkt2send, inner_pkt) | ||
|
||
|
||
@reportResults("Verify SRC IP match") | ||
def verifySrcIp(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['IP'].src = "20.0.0.10" | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify DST IP match") | ||
def verifyDstIp(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['IP'].dst = "30.0.0.10" | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify L4 SRC port match") | ||
def verifyL4SrcPort(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['TCP'].sport = 0x1235 | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify L4 DST port match") | ||
def verifyL4DstPort(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['TCP'].dport = 0x1235 | ||
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() | ||
pkt['IP'].proto = 0x7E | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify TCP flags match") | ||
def verifyTcpFlags(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['TCP'].flags = 0x12 | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify L4 SRC port range match") | ||
def verifyL4SrcPort(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['TCP'].sport = 0x123A | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify L4 DST port range match") | ||
def verifyL4DstPort(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['TCP'].dport = 0x123A | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
@reportResults("Verify IP DSCP match") | ||
def verifyIpDscp(self): | ||
pkt = self.base_pkt.copy() | ||
pkt['IP'].tos = 51 << 2 | ||
return self.runSendReceiveTest(pkt, self.src_port, self.dst_ports) | ||
|
||
|
||
def runEverflowTests(self): | ||
""" | ||
@summary: Crete and send packet to verify each ACL rule | ||
@return: Number of tests passed | ||
""" | ||
|
||
tests_passed = 0 | ||
self.tests_total = 0 | ||
|
||
if self.verifySrcIp(): | ||
tests_passed += 1 | ||
|
||
if self.verifyDstIp(): | ||
tests_passed += 1 | ||
|
||
if self.verifyL4SrcPort(): | ||
tests_passed += 1 | ||
|
||
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(): | ||
tests_passed += 1 | ||
|
||
if self.verifyL4DstPort(): | ||
tests_passed += 1 | ||
|
||
if self.verifyIpDscp(): | ||
tests_passed += 1 | ||
|
||
return tests_passed, self.tests_total | ||
|
||
|
||
def runTest(self): | ||
""" | ||
@summary: Run Everflow tests | ||
""" | ||
(tests_passed, tests_total) = self.runEverflowTests() | ||
print "Passed %d test of %d" % (tests_passed, tests_total) | ||
|
||
assert(tests_passed == tests_total) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
- name: Remove all the temporary files created by the test. | ||
file: path="{{ run_dir }}/{{ item }}" state=absent | ||
with_items: | ||
- "{{ config_files }}" | ||
|
||
- name: Remove all JSON configs from docker container filesystem. | ||
command: docker exec swss rm {{ docker_testdir }}/{{ item }} | ||
with_items: | ||
- "{{ config_files }}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#----------------------------------------- | ||
# Run all the everflow tests. | ||
#----------------------------------------- | ||
|
||
- set_fact: | ||
run_dir: /home/admin/everflow_tests | ||
out_dir: /home/admin/everflow_tests/results | ||
docker_testdir: /tmp | ||
tests_location: roles/test/tasks/everflow | ||
|
||
- name: Create run_dir | ||
file: path="{{ run_dir }}" state=directory | ||
|
||
#****************************************# | ||
# Start tests # | ||
#****************************************# | ||
|
||
- block: | ||
- name: Test Everflow configuration validation. | ||
include: "{{ tests_location }}/config_test/config_test.yml" | ||
|
||
- name: Test Everflow session activation/deactivation logic. | ||
include: "{{ tests_location }}/logic_test/logic_test.yml" | ||
|
||
always: | ||
- name: General cleanup. | ||
file: path="{{ item }}" state=absent | ||
with_items: | ||
- "{{ run_dir }}/loganalyzer.py" |
7 changes: 7 additions & 0 deletions
7
ansible/roles/test/tasks/everflow/config_test/config_delete.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
{ | ||
"MIRROR_SESSION_TABLE:session1": { | ||
}, | ||
"OP": "DEL" | ||
} | ||
] |
13 changes: 13 additions & 0 deletions
13
ansible/roles/test/tasks/everflow/config_test/config_dscp_invalid_1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[ | ||
{ | ||
"MIRROR_SESSION_TABLE:session1": { | ||
"src_ip": "1.1.1.1", | ||
"dst_ip": "2.2.2.2", | ||
"gre_type": "0x6558", | ||
"dscp": "5x0", | ||
"ttl": "10", | ||
"queue": "5" | ||
}, | ||
"OP": "SET" | ||
} | ||
] |
13 changes: 13 additions & 0 deletions
13
ansible/roles/test/tasks/everflow/config_test/config_dscp_invalid_2.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[ | ||
{ | ||
"MIRROR_SESSION_TABLE:session1": { | ||
"src_ip": "1.1.1.1", | ||
"dst_ip": "2.2.2.2", | ||
"gre_type": "0x6558", | ||
"dscp": "-1", | ||
"ttl": "10", | ||
"queue": "5" | ||
}, | ||
"OP": "SET" | ||
} | ||
] |
13 changes: 13 additions & 0 deletions
13
ansible/roles/test/tasks/everflow/config_test/config_dscp_invalid_3.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[ | ||
{ | ||
"MIRROR_SESSION_TABLE:session1": { | ||
"src_ip": "1.1.1.1", | ||
"dst_ip": "2.2.2.2", | ||
"gre_type": "0x6558", | ||
"dscp": "100", | ||
"ttl": "10", | ||
"queue": "5" | ||
}, | ||
"OP": "SET" | ||
} | ||
] |
13 changes: 13 additions & 0 deletions
13
ansible/roles/test/tasks/everflow/config_test/config_dst_ip_invalid_1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[ | ||
{ | ||
"MIRROR_SESSION_TABLE:session1": { | ||
"src_ip": "1.1.1.1", | ||
"dst_ip": "2222.2.2.2", | ||
"gre_type": "0x6558", | ||
"dscp": "50", | ||
"ttl": "10", | ||
"queue": "5" | ||
}, | ||
"OP": "SET" | ||
} | ||
] |
13 changes: 13 additions & 0 deletions
13
ansible/roles/test/tasks/everflow/config_test/config_gre_type_invalid_1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[ | ||
{ | ||
"MIRROR_SESSION_TABLE:session1": { | ||
"src_ip": "1.1.1.1", | ||
"dst_ip": "2.2.2.2", | ||
"gre_type": "0x65z58", | ||
"dscp": "50", | ||
"ttl": "10", | ||
"queue": "5" | ||
}, | ||
"OP": "SET" | ||
} | ||
] |
Oops, something went wrong.