Merge "Create dhcp rapid commit option test" am: cffe7de7a9 am: edbecc5f7b am: 342ab612d5

Original change: https://android-review.googlesource.com/c/platform/tools/test/connectivity/+/1915918

Change-Id: Ie546701a8bfad72e5ef45e3a438cf9f00ba41dee
diff --git a/acts/framework/acts/controllers/openwrt_lib/network_settings.py b/acts/framework/acts/controllers/openwrt_lib/network_settings.py
index ca1b212..f632d57 100644
--- a/acts/framework/acts/controllers/openwrt_lib/network_settings.py
+++ b/acts/framework/acts/controllers/openwrt_lib/network_settings.py
@@ -90,6 +90,7 @@
             "ipv6_prefer_option": self.remove_ipv6_prefer_option,
             "block_dns_response": self.unblock_dns_response,
             "setup_mdns": self.remove_mdns,
+            "add_dhcp_rapid_commit": self.remove_dhcp_rapid_commit,
             "setup_captive_portal": self.remove_cpative_portal
         }
         # This map contains cleanup functions to restore the configuration to
@@ -854,6 +855,18 @@
         self.service_manager.need_restart(SERVICE_DNSMASQ)
         self.commit_changes()
 
+    def add_dhcp_rapid_commit(self):
+        self.create_config_file("dhcp-rapid-commit\n","/etc/dnsmasq.conf")
+        self.config.add("add_dhcp_rapid_commit")
+        self.service_manager.need_restart(SERVICE_DNSMASQ)
+        self.commit_changes()
+
+    def remove_dhcp_rapid_commit(self):
+        self.create_config_file("","/etc/dnsmasq.conf")
+        self.config.discard("add_dhcp_rapid_commit")
+        self.service_manager.need_restart(SERVICE_DNSMASQ)
+        self.commit_changes()
+
     def start_tcpdump(self, test_name, args="", interface="br-lan"):
         """"Start tcpdump on OpenWrt.
 
diff --git a/acts_tests/tests/google/net/DhcpTest.py b/acts_tests/tests/google/net/DhcpTest.py
index 739f6ca..8923178 100644
--- a/acts_tests/tests/google/net/DhcpTest.py
+++ b/acts_tests/tests/google/net/DhcpTest.py
@@ -18,10 +18,11 @@
 from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
 from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
 from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
+from scapy.all import rdpcap, DHCP
 
 WLAN = "wlan0"
 PING_ADDR = "google.com"
-
+RAPID_COMMIT_OPTION = (80, b'')
 
 class DhcpTest(WifiBaseTest):
     """DHCP related test for Android."""
@@ -30,14 +31,23 @@
         self.dut = self.android_devices[0]
 
         wutils.wifi_test_device_init(self.dut)
+        req_params = []
+        opt_param = ["wifi_network", "configure_OpenWrt"]
+        self.unpack_userparams(
+            req_param_names=req_params, opt_param_names=opt_param)
         asserts.assert_true(OPENWRT in self.user_params,
                             "OpenWrtAP is not in testbed.")
+
         self.openwrt = self.access_points[0]
-        self.configure_openwrt_ap_and_start(wpa_network=True)
-        self.wifi_network = self.openwrt.get_wifi_network()
+        if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+            self.dut.log.info("Skip configure Wifi interface due to config setup.")
+        else:
+            self.configure_openwrt_ap_and_start(wpa_network=True)
+            self.wifi_network = self.openwrt.get_wifi_network()
         self.openwrt.network_setting.setup_ipv6_bridge()
         asserts.assert_true(self.openwrt.verify_wifi_status(),
                             "OpenWrt Wifi interface is not ready.")
+
     def teardown_class(self):
         """Reset wifi to make sure VPN tears down cleanly."""
         wutils.reset_wifi(self.dut)
@@ -70,6 +80,25 @@
                 time.sleep(1)
         return False
 
+    def verify_dhcp_packet(self, packets, support_rapid_commit):
+        for pkt in packets:
+            if pkt.haslayer(DHCP):
+                if pkt[DHCP].options[0][1]==1:
+                    send_option = RAPID_COMMIT_OPTION in pkt[DHCP].options
+                    asserts.assert_true(send_option == support_rapid_commit,
+                                        "Unexpected result in DHCP DISCOVER.")
+                elif pkt[DHCP].options[0][1]==2:
+                    asserts.assert_true( not support_rapid_commit,
+                                         "Should not find DHCP OFFER when RAPID_COMMIT_OPTION supported.")
+                elif pkt[DHCP].options[0][1]==3:
+                    asserts.assert_true( not support_rapid_commit,
+                                         "Should not find DHCP REQUEST when RAPID_COMMIT_OPTION supported.")
+                elif pkt[DHCP].options[0][1]==5:
+                    send_option = RAPID_COMMIT_OPTION in pkt[DHCP].options
+                    asserts.assert_true(send_option == support_rapid_commit,
+                                    "Unexpected result in DHCP ACK.")
+
+    @test_tracker_info(uuid="01148659-6a3d-4a74-88b6-04b19c4acaaa")
     def test_ipv4_ipv6_network(self):
         """Verify device can get both ipv4 ipv6 address."""
         wutils.connect_to_wifi_network(self.dut, self.wifi_network)
@@ -79,6 +108,7 @@
         asserts.assert_true(self._verify_ping(), "Fail to ping on ipv4.")
         asserts.assert_true(self._verify_ping("6"), "Fail to ping on ipv6.")
 
+    @test_tracker_info(uuid="d3f37ba7-504e-48fc-95be-6eca9a148e4a")
     def test_ipv6_only_prefer_option(self):
         """Verify DUT can only get ipv6 address and ping out."""
         self.openwrt.network_setting.add_ipv6_prefer_option()
@@ -90,3 +120,32 @@
                              "Should not ping on success on ipv4.")
         asserts.assert_true(self._verify_ping("6"),
                             "Fail to ping on ipv6.")
+        self.openwrt.network_setting.remove_ipv6_prefer_option()
+
+    @test_tracker_info(uuid="a16f2a3c-e3ca-4fca-b3ee-bccb5cf34bab")
+    def test_dhcp_rapid_commit(self):
+        """Verify DUT can run with rapid commit on IPv4."""
+        self.dut.adb.shell("device_config put connectivity dhcp_rapid_commit_version 1")
+        self.openwrt.network_setting.add_dhcp_rapid_commit()
+        remote_pcap_path = \
+            self.openwrt.network_setting.start_tcpdump(self.test_name)
+        wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+        local_pcap_path = self.openwrt.network_setting.stop_tcpdump(
+            remote_pcap_path, self.dut.device_log_path)
+        self.dut.log.info("pcap file path : %s" % local_pcap_path)
+        packets = rdpcap(local_pcap_path)
+        self.verify_dhcp_packet(packets, True)
+        self.openwrt.network_setting.remove_dhcp_rapid_commit()
+
+    @test_tracker_info(uuid="cddb3d33-e5ef-4efd-8ae5-1325010a05c8")
+    def test_dhcp_4_way_handshake(self):
+        """Verify DUT can run with rapid commit on IPv4."""
+        self.dut.adb.shell("device_config put connectivity dhcp_rapid_commit_version 0")
+        remote_pcap_path = \
+            self.openwrt.network_setting.start_tcpdump(self.test_name)
+        wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+        local_pcap_path = self.openwrt.network_setting.stop_tcpdump(
+            remote_pcap_path, self.dut.device_log_path)
+        self.dut.log.info("pcap file path : %s" % local_pcap_path)
+        packets = rdpcap(local_pcap_path)
+        self.verify_dhcp_packet(packets, False)