diff --git a/ansible/roles/test/files/acstests/everflow_policer_test.py b/ansible/roles/test/files/acstests/everflow_policer_test.py new file mode 100644 index 00000000000..b09e30a74e5 --- /dev/null +++ b/ansible/roles/test/files/acstests/everflow_policer_test.py @@ -0,0 +1,149 @@ +''' +Description: This file contains the EVERFLOW policer test + +Usage: Examples of how to use: + ptf --test-dir acstests everflow_policer_test.EverflowPolicerTest --platform remote -t 'router_mac="00:02:03:04:05:00";src_port="20";dst_ports="21,22";verbose=True' --relax +''' + + +import ptf +import ptf.packet as scapy +import ptf.dataplane as dataplane +import ptf.testutils as testutils +from ptf.base_tests import BaseTest +from ptf.mask import Mask + +class EverflowPolicerTest(BaseTest): + + GRE_PROTOCOL_NUMBER = 47 + NUM_OF_TOTAL_PACKETS = 200 + + + def __init__(self): + ''' + @summary: constructor + ''' + BaseTest.__init__(self) + self.test_params = testutils.test_params_get() + + + def greFilter(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 the test + ''' + print "" + + self.dataplane = ptf.dataplane_instance + self.hwsku = self.test_params['hwsku'] + self.asic_type = self.test_params['asic_type'] + self.router_mac = self.test_params['router_mac'] + self.session_src_ip = "1.1.1.1" + self.session_dst_ip = "2.2.2.2" + self.session_ttl = 1 + self.session_dscp = 8 + self.src_port = int(self.test_params['src_port']) + self.dst_mirror_ports = [int(p) for p in self.test_params['dst_mirror_ports'].split(",") if p] + self.dst_ports = [int(p) for p in self.test_params['dst_ports'].split(",")] + + 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_dscp = 9, + ip_ttl = 64) + + def checkOriginalFlow(self): + """ + @summary: Send traffic & check how many original packets are received + @return: count: number of original packets received + """ + exp_pkt = self.base_pkt.copy() + exp_pkt['Ethernet'].src = self.router_mac + exp_pkt['IP'].ttl = self.base_pkt['IP'].ttl - 1 + + masked_exp_pkt = Mask(exp_pkt) + masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") + + 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: + count += 1 + elif count == 0: + print "The first original packet is not recieved" + assert False # Fast failure without waiting for full iteration + print "Recieved " + str(count) + " original packets" + return count + + def checkMirroredFlow(self): + """ + @summary: Send traffic & check how many mirrored packets are received + @return: count: number of mirrored packets received + """ + exp_pkt = testutils.simple_gre_packet( + eth_src = self.router_mac, + ip_src = self.session_src_ip, + ip_dst = self.session_dst_ip, + ip_dscp = self.session_dscp, + ip_id = 0, + #ip_flags = 0x10, # need to upgrade ptf version to support it + ip_ttl = self.session_ttl, + inner_frame = self.base_pkt) + + exp_pkt['GRE'].proto = 0x88be + + 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.IP, "flags") + masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") + + 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: + count += 1 + elif count == 0: + print "The first mirrored packet is not recieved" + assert False # Fast failure without waiting for full iteration + print "Received " + str(count) + " mirrored packets after rate limiting" + return count + + + def runTest(self): + """ + @summary: Run EVERFLOW Policer Test + """ + + # Send traffic and verify the original traffic is not rate limited + count = self.checkOriginalFlow() + assert count == self.NUM_OF_TOTAL_PACKETS + + testutils.add_filter(self.greFilter) + + # Send traffic and verify the mirroed traffic is rate limited + count = self.checkMirroredFlow() + assert count > 100 and count < self.NUM_OF_TOTAL_PACKETS # cbs = cir = 100 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 1779766979f..01851ded32e 100644 --- a/ansible/roles/test/tasks/everflow_testbed/get_port_info.yml +++ b/ansible/roles/test/tasks/everflow_testbed/get_port_info.yml @@ -5,6 +5,7 @@ set_fact: tor_ports: [] spine_ports: [] + spine_ptf_ports: [] dst_port_1_is_lag_member: "" dst_port_1_ptf_id: "" dst_port_2: "" @@ -21,7 +22,7 @@ when: "'T0' in item.value.name" - name: Print tor ports - debug: msg="{{ tor_ports }}" + debug: msg={{ tor_ports }} - name: Get spine ports set_fact: @@ -30,7 +31,12 @@ when: "'T2' in item.value.name" - name: Print spine ports - debug: msg="{{ spine_ports }}" + debug: msg={{ spine_ports }} + +- name: Define spine PTF ports + set_fact: + spine_ptf_ports: "{{ spine_ptf_ports + [minigraph_port_indices[item] | string] }}" + with_items: "{{ spine_ports }}" - name: Define SRC port variables. set_fact: diff --git a/ansible/roles/test/tasks/everflow_testbed/run_test.yml b/ansible/roles/test/tasks/everflow_testbed/run_test.yml index c0b129b0e56..847a675333d 100644 --- a/ansible/roles/test/tasks/everflow_testbed/run_test.yml +++ b/ansible/roles/test/tasks/everflow_testbed/run_test.yml @@ -69,6 +69,9 @@ - name: Run testcase 7 - ECMP route change (remove next hop used by session). include: roles/test/tasks/everflow_testbed/testcase_7.yml + - name: Run testcase 8 - Policer enforced with DSCP value/mask + include: roles/test/tasks/everflow_testbed/testcase_8.yml + always: - name: Remove route to unresolved next hop. shell: vtysh -e "conf t" -e "no ip route {{ unresolved_nexthop_prefix }} {{ dst_port_2 }}" diff --git a/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml b/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml new file mode 100644 index 00000000000..364dfee4dfe --- /dev/null +++ b/ansible/roles/test/tasks/everflow_testbed/testcase_8.yml @@ -0,0 +1,76 @@ +# Test case 8 - Policer enforced DSCP value/mask test + +- set_fact: + policer_name: TEST_POLICER + policer_session_name: TEST_POLICER_SESSION + dscp_table_name: EVERFLOW_DSCP + +- name: Create route with next hop {{ dst_port_1 }}. + shell: vtysh -e "conf t" -e "ip route {{ session_prefix_1 }} {{ neighbor_info_1['addr'] }}" + become: yes + +- block: + - name: Create a policer + shell: | + redis-cli -n 4 hmset "POLICER|{{policer_name}}" "meter_type" "packets" "mode" "sr_tcm" "cir" "100" "cbs" "100" "red_packet_action" "drop" + become: yes + + - name: Create a policer enforced mirror session + shell: | + config mirror_session add {{policer_session_name}} {{session_src_ip}} {{session_dst_ip}} {{session_dscp}} {{session_ttl}} --policer {{policer_name}} + become: yes + + - name: Create an ACL table with MIRROR_DSCP type + shell: config acl add table {{dscp_table_name}} "MIRROR_DSCP" --description "EVERFLOW_TEST" + become: yes + + - name: Create a rule with DSCP value and mask + shell: | + redis-cli -n 4 hmset "ACL_RULE|{{dscp_table_name}}|RULE_1" "PRIORITY" "9999" "MIRROR_ACTION" "{{policer_session_name}}" "DSCP" "8/56" + become: yes + + - name: "Start PTF runner" + include: roles/test/tasks/ptf_runner.yml + vars: + ptf_test_name: EVERFLOW Policer Test + ptf_test_dir: acstests + ptf_test_path: everflow_policer_test.EverflowPolicerTest + ptf_platform: remote + ptf_platform_dir: ptftests + ptf_test_params: + - asic_type='{{sonic_asic_type}}' + - hwsku='{{sonic_hwsku}}' + - router_mac='{{ansible_Ethernet0['macaddress']}}' + - src_port='{{src_port_ptf_id}}' + - dst_ports='{{",".join((spine_ptf_ports))}}' + - dst_mirror_ports='{{dst_port_1_ptf_id}}' + ptf_extra_options: "--relax --debug info" + + always: + - name: Remove route + shell: vtysh -e "conf t" -e "no ip route {{ session_prefix_1 }} {{ neighbor_info_1['addr'] }}" + ignore_errors: yes + become: yes + + - name: Create a policer + shell: | + redis-cli -n 4 del "POLICER|{{policer_name}}" + ignore_errors: yes + become: yes + + - name: Create a policer enforced mirror session + shell: | + config mirror_session remove {{policer_session_name}} + ignore_errors: yes + become: yes + + - name: Create an ACL table with MIRROR_DSCP type + shell: config acl remove table {{dscp_table_name}} + ignore_errors: yes + become: yes + + - name: Create a rule with DSCP value and mask + shell: | + redis-cli -n 4 del "ACL_RULE|{{dscp_table_name}}|RULE_1" + ignore_errors: yes + become: yes