diff --git a/ansible/roles/test/files/ptftests/py3/dhcp_relay_test.py b/ansible/roles/test/files/ptftests/py3/dhcp_relay_test.py index 7b911e9f5e8..9952e4dd754 100644 --- a/ansible/roles/test/files/ptftests/py3/dhcp_relay_test.py +++ b/ansible/roles/test/files/ptftests/py3/dhcp_relay_test.py @@ -174,6 +174,9 @@ def setUp(self): self.portchannels_ip_list = self.test_params.get('portchannels_ip_list', None) self.agent_relay_mode = self.test_params.get('agent_relay_mode', None) self.max_hop_count = self.test_params.get('max_hop_count', None) + self.client_giaddr = self.test_params.get('client_giaddr', self.switch_loopback_ip) + self.incoming_hop_count = self.test_params.get('incoming_hop_count', None) + self.expected_forward = self.test_params.get('expected_forward', None) self.client_vrf = self.test_params.get('client_vrf', None) self.dhcpv4_disable_flag = self.test_params.get('dhcpv4_disable_flag', None) if self.relay_agent == "sonic-relay-agent": @@ -299,8 +302,11 @@ def create_dhcp_discover_packet(self, dst_mac=BROADCAST_MAC, src_port=DHCP_CLIEN discover_packet[scapy.Ether].dst = self.uplink_mac discover_packet[scapy.IP].src = self.client_ip discover_packet[scapy.IP].dst = self.switch_loopback_ip - discover_packet[scapy.BOOTP].hops = self.max_hop_count if self.max_hop_count == self.MAX_HOP_COUNT else 1 - discover_packet[scapy.BOOTP].giaddr = self.switch_loopback_ip + discover_packet[scapy.BOOTP].hops = ( + self.incoming_hop_count if self.incoming_hop_count is not None + else self.max_hop_count if self.max_hop_count == self.MAX_HOP_COUNT else 1 + ) + discover_packet[scapy.BOOTP].giaddr = self.client_giaddr discover_packet[scapy.DHCP].options.insert( discover_packet[scapy.DHCP].options.index("end"), (82, relay_option82) @@ -1203,11 +1209,33 @@ def check_relayed_pkts_on_server_side(self, mask, pkt, packet_type): logger.info("Expect receiving {} packets from port [{}]".format(packet_type, self.server_port_indices)) log_dhcp_packet_info(pkt) num_expected_packets = self.num_dhcp_servers - if self.agent_relay_mode == "discard" or self.dhcpv4_disable_flag or self.max_hop_count == self.MAX_HOP_COUNT: - # Expected result: No packet sent + if self.expected_forward is None: + expected_forward = not ( + self.agent_relay_mode == "discard" + or self.dhcpv4_disable_flag + or self.max_hop_count == self.MAX_HOP_COUNT + ) + else: + expected_forward = self.expected_forward + if expected_forward: + packet_mask = mask + else: num_expected_packets = 0 + unexpected_packet = ( + scapy.Ether(src=self.uplink_mac) + / scapy.IP() + / scapy.UDP(sport=self.DHCP_SERVER_PORT, dport=self.DHCP_SERVER_PORT) + ) + packet_mask = Mask(unexpected_packet) + packet_mask.set_do_not_care_scapy(scapy.Ether, "dst") + for field in ("version", "ihl", "tos", "len", "id", "flags", + "frag", "ttl", "chksum", "src", "dst", "options"): + packet_mask.set_do_not_care_scapy(scapy.IP, field) + packet_mask.set_do_not_care_scapy(scapy.UDP, "chksum") + packet_mask.set_do_not_care_scapy(scapy.UDP, "len") + packet_mask.set_ignore_extra_bytes() captured_count = testutils.count_matched_packets_all_ports( - self, mask, self.server_port_indices) + self, packet_mask, self.server_port_indices) self.assertTrue(captured_count == num_expected_packets, "Failed: %s packet counts are not equal %d != %d" % (packet_type, captured_count, num_expected_packets)) diff --git a/tests/dhcp_relay/test_dhcpv4_relay.py b/tests/dhcp_relay/test_dhcpv4_relay.py index bd4f2cede48..94bfce4deba 100644 --- a/tests/dhcp_relay/test_dhcpv4_relay.py +++ b/tests/dhcp_relay/test_dhcpv4_relay.py @@ -439,6 +439,67 @@ def test_dhcp_relay_agent_mode( sonic_dhcp_relay_config(duthost, dut_dhcp_relay_data) +def test_dhcp_relay_first_hop_option82_dropped( + ptfhost, + dut_dhcp_relay_data, + validate_dut_routes_exist, + testing_config, + setup_standby_ports_on_rand_unselected_tor, + rand_unselected_dut, + toggle_all_simulator_ports_to_rand_selected_tor_m, # noqa: F811 + relay_agent # noqa: F811 +): + """Verify native relay drops first-hop requests that already contain Option 82.""" + testing_mode, duthost = testing_config + + try: + for dhcp_relay in dut_dhcp_relay_data: + vlan = str(dhcp_relay['downlink_vlan_iface']['name']) + dhcp_servers = ",".join(dhcp_relay['downlink_vlan_iface']['dhcp_server_addrs']) + duthost.shell(f'config dhcpv4_relay del {vlan}') + duthost.shell(f'config dhcpv4_relay add --dhcpv4-servers {dhcp_servers}' + f' --agent-relay-mode discard {vlan}') + + ptf_runner( + ptfhost, + "ptftests", + "dhcp_relay_test.DHCPTest", + platform_dir="ptftests", + params={ + "hostname": duthost.hostname, + "client_port_index": dhcp_relay['client_iface']['port_idx'], + "other_client_port": repr(dhcp_relay['other_client_ports']), + "client_iface_alias": str(dhcp_relay['client_iface']['alias']), + "leaf_port_indices": repr(dhcp_relay['uplink_port_indices']), + "num_dhcp_servers": len(dhcp_relay['downlink_vlan_iface']['dhcp_server_addrs']), + "server_ip": dhcp_relay['downlink_vlan_iface']['dhcp_server_addrs'], + "relay_iface_ip": str(dhcp_relay['downlink_vlan_iface']['addr']), + "relay_iface_mac": str(dhcp_relay['downlink_vlan_iface']['mac']), + "relay_iface_netmask": str(dhcp_relay['downlink_vlan_iface']['mask']), + "dest_mac_address": BROADCAST_MAC, + "client_udp_src_port": DEFAULT_DHCP_CLIENT_PORT, + "switch_loopback_ip": dhcp_relay['switch_loopback_ip'], + "uplink_mac": str(dhcp_relay['uplink_mac']), + "testing_mode": testing_mode, + "kvm_support": True, + "relay_agent": relay_agent, + "agent_relay_mode": "discard", + "client_giaddr": "0.0.0.0", + "incoming_hop_count": 0, + "expected_forward": False, + "downlink_vlan_iface_name": str(dhcp_relay['downlink_vlan_iface']['name']), + }, + log_file="/tmp/test_dhcp_relay_first_hop_option82.log", + is_python3=True + ) + except LogAnalyzerError as err: + logger.error("Unable to find expected log in syslog") + raise err + finally: + sonic_dhcp_relay_unconfig(duthost, dut_dhcp_relay_data) + sonic_dhcp_relay_config(duthost, dut_dhcp_relay_data) + + @pytest.mark.parametrize("testcase", ["vrf_selection", "source_intf", "server_id_override"]) def test_dhcp_relay_with_non_default_vrf( ptfhost,