diff --git a/tests/packet_trimming/constants.py b/tests/packet_trimming/constants.py index 0ebbd45a1..bbfcc74e3 100644 --- a/tests/packet_trimming/constants.py +++ b/tests/packet_trimming/constants.py @@ -28,6 +28,7 @@ PACKET_COUNT = 1000 BATCH_PACKET_COUNT = 10000 ECN = 2 # ECN Capable Transport(0), ECT(0) +PACKET_SIZE_MARGIN = 4 # Buffer configuration constants TRIM_QUEUE_PROFILE = "egress_lossy_profile" diff --git a/tests/packet_trimming/packet_trimming_helper.py b/tests/packet_trimming/packet_trimming_helper.py index 91012c2b6..abcbbd89f 100644 --- a/tests/packet_trimming/packet_trimming_helper.py +++ b/tests/packet_trimming/packet_trimming_helper.py @@ -25,7 +25,8 @@ SRV6_INNER_SRC_IP, SRV6_INNER_DST_IP, DEFAULT_QUEUE_SCHEDULER_CONFIG, SRV6_UNIFORM_MODE, SRV6_OUTER_SRC_IPV6, SRV6_INNER_SRC_IPV6, ECN, SRV6_INNER_DST_IPV6, SRV6_UN, ASYM_PORT_1_DSCP, ASYM_PORT_2_DSCP, - SCHEDULER_TYPE, SCHEDULER_WEIGHT, SCHEDULER_PIR, SCHEDULER_METER_TYPE) + SCHEDULER_TYPE, SCHEDULER_WEIGHT, SCHEDULER_PIR, SCHEDULER_METER_TYPE, + PACKET_SIZE_MARGIN) from tests.packet_trimming.packet_trimming_config import PacketTrimmingConfig logger = logging.getLogger(__name__) @@ -254,7 +255,7 @@ def generate_packet(duthost, packet_type, dst_addr, send_pkt_size, send_pkt_dscp exp_packet = testutils.simple_udpv6_packet(**recv_params) # Create masked expected packet - masked_exp_packet = Mask(exp_packet) + masked_exp_packet = Mask(exp_packet, ignore_extra_bytes=True) # Set fields to ignore in packet matching # Common Ethernet header fields to ignore @@ -426,6 +427,18 @@ def delete_blocking_scheduler(duthost): logger.info(f"Successfully deleted blocking scheduler: {BLOCK_DATA_PLANE_SCHEDULER_NAME}") +def validate_packet_size(pkt_size, pkt_size_exp): + """ + Validate packet size against expected size +/- PACKET_SIZE_MARGIN + + Args: + pkt_size: the packet's actual size + pkt_size_exp: the packet's expected size + """ + pytest_assert(pkt_size_exp - PACKET_SIZE_MARGIN <= pkt_size <= pkt_size_exp + PACKET_SIZE_MARGIN, + f"Packet size expected {pkt_size_exp} +/- {PACKET_SIZE_MARGIN}, was: {pkt_size} ") + + def validate_scheduler_configuration(duthost, dut_port, queue, expected_scheduler): """ Validate that the scheduler configuration is applied correctly for a specific queue. @@ -875,7 +888,7 @@ def verify_packet_trimming(duthost, ptfadapter, ingress_port, egress_port, block dst_addr, send_pkt_size, send_pkt_dscp, - recv_pkt_size, + recv_pkt_size - PACKET_SIZE_MARGIN, recv_pkt_dscp ) @@ -905,12 +918,13 @@ def verify_packet_trimming(duthost, ptfadapter, ingress_port, egress_port, block if expect_packets: logger.info( f"Expecting packets on ports {verify_ports} with size {recv_pkt_size} and DSCP {recv_pkt_dscp}") - testutils.verify_packet_any_port( + _, matched = testutils.verify_packet_any_port( ptfadapter, exp_pkt, ports=verify_ports, timeout=timeout ) + validate_packet_size(len(matched), recv_pkt_size) logger.info( f"Successfully verified {packet_type} packet trimming with size {recv_pkt_size} " f"and DSCP {recv_pkt_dscp}") @@ -2045,7 +2059,7 @@ def validate_srv6_function(duthost, ptfadapter, dscp_mode, ingress_port, egress_ # - SRv6 packet without SRH: IPv6 (40) + IPv4 (20) + UDP (8) + Payload = 256 # - SRv6 packet with SRH: IPv6 (40) + SRH (40) + IPv4 (20) + UDP (8) + Payload = 256 - actual_recv_pkt_size = recv_pkt_size - ipv6_header_len + actual_recv_pkt_size = recv_pkt_size - ipv6_header_len - PACKET_SIZE_MARGIN srv6_pkt, exp_pkt = create_srv6_packet_for_trimming( outer_src_mac=DUMMY_MAC, @@ -2077,15 +2091,25 @@ def validate_srv6_function(duthost, ptfadapter, dscp_mode, ingress_port, egress_ else: verify_ports = [egress_port['ptf_id']] - send_verify_srv6_packet_for_trimming( - ptfadapter=ptfadapter, - pkt=srv6_pkt, - exp_pkt=exp_pkt, - exp_pro=srv6_packet["exp_process_result"], - ptf_src_port_id=ingress_port['ptf_id'], - ptf_dst_port_ids=verify_ports, - packet_num=PACKET_COUNT - ) + ptfadapter.dataplane.flush() + + logger.info(f"Send SRv6 packet(s) from PTF port {ingress_port['ptf_id']} to upstream") + testutils.send(ptfadapter, ingress_port['ptf_id'], srv6_pkt, count=PACKET_COUNT) + + logger.info('SRv6 packet format:\n ---------------------------') + logger.info(f'{dump_packet_detail(srv6_pkt)}\n---------------------------') + logger.info('Expect receive SRv6 packet format:\n ---------------------------') + logger.info(f'{dump_packet_detail(exp_pkt.exp_pkt)}\n---------------------------') + + if srv6_packet['exp_process_result'] == 'forward': + _, matched = testutils.verify_packet_any_port(ptfadapter, exp_pkt, ports=verify_ports) + validate_packet_size(len(matched), recv_pkt_size) + logger.info('Successfully received packets') + elif srv6_packet['exp_process_result'] == 'drop': + testutils.verify_no_packet_any(ptfadapter, exp_pkt, ports=verify_ports) + logger.info(f'No packet received on {verify_ports}') + else: + logger.error(f"Wrong expected process result: {srv6_packet['exp_process_result']}") def create_srv6_packet_for_trimming( @@ -2233,7 +2257,7 @@ def create_srv6_packet_for_trimming( ) exp_pkt['IPv6'].hlim -= 1 - exp_pkt = Mask(exp_pkt) + exp_pkt = Mask(exp_pkt, ignore_extra_bytes=True) logger.info('Do not care packet ethernet destination address') exp_pkt.set_do_not_care_packet(scapy.Ether, 'dst') @@ -2285,47 +2309,6 @@ def create_srv6_packet_for_trimming( return srv6_pkt, exp_pkt -def send_verify_srv6_packet_for_trimming( - ptfadapter, - pkt, - exp_pkt, - exp_pro, - ptf_src_port_id, - ptf_dst_port_ids, - packet_num=10): - """ - Send and verify SRv6 packets - - Args: - ptfadapter: PTF adapter object - pkt: Packet to send - exp_pkt: Expected packet - exp_pro (str): Expected process result ('forward' or 'drop') - ptf_src_port_id (int): Source PTF port ID - ptf_dst_port_ids: - packet_num (int): Number of packets to send (default: 10) - """ - ptfadapter.dataplane.flush() - logger.info(f'Send SRv6 packet(s) from PTF port {ptf_src_port_id} to upstream') - testutils.send(ptfadapter, ptf_src_port_id, pkt, count=packet_num) - logger.info('SRv6 packet format:\n ---------------------------') - logger.info(f'{dump_packet_detail(pkt)}\n---------------------------') - logger.info('Expect receive SRv6 packet format:\n ---------------------------') - logger.info(f'{dump_packet_detail(exp_pkt.exp_pkt)}\n---------------------------') - - try: - if exp_pro == 'forward': - testutils.verify_packet_any_port(ptfadapter, exp_pkt, ports=ptf_dst_port_ids) - logger.info('Successfully received packets') - elif exp_pro == 'drop': - testutils.verify_no_packet_any(ptfadapter, exp_pkt, ports=ptf_dst_port_ids) - logger.info(f'No packet received on {ptf_dst_port_ids}') - else: - logger.error(f'Wrong expected process result: {exp_pro}') - except AssertionError as detail: - raise detail - - def check_connected_route_ready(duthost, egress_port): """ Check if the route for the specified interface is ready. @@ -2575,7 +2558,7 @@ def verify_normal_packet(duthost, ptfadapter, ingress_port, egress_port, send_pk dst_addr, send_pkt_size, send_pkt_dscp, - recv_pkt_size, + recv_pkt_size - PACKET_SIZE_MARGIN, recv_pkt_dscp ) @@ -2605,12 +2588,13 @@ def verify_normal_packet(duthost, ptfadapter, ingress_port, egress_port, send_pk # Verify packet if expect_packets: logger.info(f"Expecting packets on ports {verify_ports} with size {recv_pkt_size} and DSCP {recv_pkt_dscp}") - testutils.verify_packet_any_port( + _, matched = testutils.verify_packet_any_port( ptfadapter, exp_pkt, ports=verify_ports, timeout=timeout ) + validate_packet_size(len(matched), recv_pkt_size) logger.info(f"Successfully verified normal packet with size {recv_pkt_size}") else: logger.info(f"Expecting NO packets on ports {verify_ports}")