shill: acquire ip addresses for wifi (via dhcp), and signal when
the service is ready
BUG=chromium-os:20191
TEST=unittest, network_WiFiManager/000_SSID_Length_Limit
note: with this CL, 000_SSID_Length_Limit connects to the
open network, but fails on the hidden network. hidden network
support requires shill to implement Manager.GetService.
Change-Id: I71d1634fb3fc48de36fd2bf828969bfe0b3a46f6
Reviewed-on: http://gerrit.chromium.org/gerrit/7466
Tested-by: mukesh agrawal <quiche@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
diff --git a/cellular_service.h b/cellular_service.h
index c1636a8..2e464ee 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -60,9 +60,6 @@
const std::string &roaming_state() const { return roaming_state_; }
void set_roaming_state(const std::string &state) { roaming_state_ = state; }
- protected:
- virtual std::string CalculateState() { return "idle"; }
-
private:
static const char kServiceType[];
diff --git a/ethernet_service.h b/ethernet_service.h
index d0dbf0b..88aa8b5 100644
--- a/ethernet_service.h
+++ b/ethernet_service.h
@@ -32,9 +32,6 @@
// ethernet_<MAC>
virtual std::string GetStorageIdentifier(const std::string &mac);
- protected:
- virtual std::string CalculateState() { return "idle"; }
-
private:
static const char kServiceType[];
diff --git a/mock_dhcp_provider.h b/mock_dhcp_provider.h
index 6fd9aa7..47b12fe 100644
--- a/mock_dhcp_provider.h
+++ b/mock_dhcp_provider.h
@@ -8,7 +8,9 @@
#include <base/basictypes.h>
#include <gmock/gmock.h>
+#include "shill/dhcp_config.h"
#include "shill/dhcp_provider.h"
+#include "shill/refptr_types.h"
namespace shill {
diff --git a/service.cc b/service.cc
index 2740065..d1ed9a4 100644
--- a/service.cc
+++ b/service.cc
@@ -176,7 +176,7 @@
failure_ = kFailureUnknown;
}
manager_->UpdateService(this);
- // TODO(pstew): Broadcast property change notification via control interface
+ adaptor_->EmitStringChanged(flimflam::kStateProperty, CalculateState());
}
void Service::SetFailure(ConnectFailure failure) {
@@ -265,6 +265,16 @@
void Service::set_profile(const ProfileRefPtr &p) { profile_ = p; }
+string Service::CalculateState() {
+ switch (state_) {
+ case kStateConnected:
+ return flimflam::kStateReady;
+ default:
+ // TODO(quiche): provide strings for other states
+ return flimflam::kStateIdle;
+ }
+}
+
void Service::HelpRegisterDerivedBool(const string &name,
bool(Service::*get)(void),
bool(Service::*set)(const bool&)) {
diff --git a/service.h b/service.h
index 8ad5132..836d38e 100644
--- a/service.h
+++ b/service.h
@@ -139,7 +139,7 @@
// Returns true if a character is allowed to be in a service storage id.
static bool LegalChar(char a) { return isalnum(a) || a == '_'; }
- virtual std::string CalculateState() = 0;
+ virtual std::string CalculateState();
void HelpRegisterDerivedBool(const std::string &name,
bool(Service::*get)(void),
diff --git a/service_unittest.cc b/service_unittest.cc
index f90f162..7d7d4fb 100644
--- a/service_unittest.cc
+++ b/service_unittest.cc
@@ -233,6 +233,10 @@
EXPECT_EQ(Service::kFailureUnknown, service_->failure());
ServiceConstRefPtr service_ref(service_);
+
+ // TODO(quiche): make this EXPECT_CALL work (crosbug.com/20154)
+ // EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
+ // EmitStringChanged(flimflam::kStateProperty, _));
EXPECT_CALL(mock_manager_, UpdateService(service_ref));
service_->SetState(Service::kStateConnected);
// A second state change shouldn't cause another update
diff --git a/wifi.cc b/wifi.cc
index e712ca2..4ea6547 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -7,6 +7,8 @@
#include <time.h>
#include <stdio.h>
#include <string.h>
+#include <netinet/ether.h>
+#include <linux/if.h>
#include <map>
#include <string>
@@ -58,7 +60,8 @@
bgscan_short_interval_(0),
bgscan_signal_threshold_(0),
scan_pending_(false),
- scan_interval_(0) {
+ scan_interval_(0),
+ link_up_(false) {
PropertyStore *store = this->store();
store->RegisterString(flimflam::kBgscanMethodProperty, &bgscan_method_);
store->RegisterUint16(flimflam::kBgscanShortIntervalProperty,
@@ -147,6 +150,26 @@
return type == Device::kWifi;
}
+void WiFi::LinkEvent(unsigned int flags, unsigned int change) {
+ // TODO(quiche): figure out how to relate these events to supplicant
+ // events. e.g., may be we can ignore LinkEvent, in favor of events
+ // from SupplicantInterfaceProxy?
+ Device::LinkEvent(flags, change);
+ if ((flags & IFF_LOWER_UP) != 0 && !link_up_) {
+ LOG(INFO) << link_name() << " is up; should start L3!";
+ link_up_ = true;
+ if (AcquireDHCPConfig()) {
+ SetServiceState(Service::kStateConfiguring);
+ } else {
+ LOG(ERROR) << "Unable to acquire DHCP config.";
+ }
+ } else if ((flags & IFF_LOWER_UP) == 0 && link_up_) {
+ link_up_ = false;
+ // TODO(quiche): attempt to reconnect to current SSID, another SSID,
+ // or initiate a scan.
+ }
+}
+
void WiFi::BSSAdded(
const ::DBus::Path &BSS,
const std::map<string, ::DBus::Variant> &properties) {
@@ -178,7 +201,7 @@
DBus::MessageIter writer;
DBus::Path network_path;
- // TODO(quiche): if already connected, disconnect
+ // TODO(quiche): handle cases where already connected
add_network_args[kSupplicantPropertyNetworkMode].writer().
append_uint32(WiFiEndpoint::ModeStringToUint(service->mode()));
@@ -194,6 +217,14 @@
supplicant_interface_proxy_->AddNetwork(add_network_args);
supplicant_interface_proxy_->SelectNetwork(network_path);
// XXX add to favorite networks list?
+
+ // SelectService here (instead of in LinkEvent, like Ethernet), so
+ // that, if we fail to bring up L2, we can attribute failure correctly.
+ //
+ // TODO(quiche): when we add code for dealing with connection failures,
+ // reconsider if this is the right place to change the selected service.
+ // see discussion in crosbug.com/20191.
+ SelectService(service);
}
void WiFi::ScanDoneTask() {
diff --git a/wifi.h b/wifi.h
index c58aa8c..8128965 100644
--- a/wifi.h
+++ b/wifi.h
@@ -35,6 +35,7 @@
virtual void Stop();
virtual void Scan();
virtual bool TechnologyIs(const Technology type) const;
+ virtual void LinkEvent(unsigned int flags, unsigned int change);
// called by SupplicantInterfaceProxy, in response to events from
// wpa_supplicant.
@@ -75,8 +76,9 @@
int32 bgscan_signal_threshold_;
bool scan_pending_;
uint16 scan_interval_;
+ bool link_up_;
- friend class WiFiMainTest; // access to supplicant_*_proxy_ fields
+ friend class WiFiMainTest; // access to supplicant_*_proxy_, link_up_
DISALLOW_COPY_AND_ASSIGN(WiFi);
};
diff --git a/wifi_service.h b/wifi_service.h
index 9f654ab..8e10df2 100644
--- a/wifi_service.h
+++ b/wifi_service.h
@@ -41,9 +41,6 @@
const std::string &key_management() const;
const std::vector<uint8_t> &ssid() const;
- protected:
- virtual std::string CalculateState() { return "idle"; }
-
private:
void ConnectTask();
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index 2d5cd9f..5cb2c76 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -4,6 +4,9 @@
#include "shill/wifi.h"
+#include <netinet/ether.h>
+#include <linux/if.h>
+
#include <map>
#include <string>
#include <vector>
@@ -19,6 +22,8 @@
#include "shill/dbus_adaptor.h"
#include "shill/manager.h"
#include "shill/mock_device.h"
+#include "shill/mock_dhcp_config.h"
+#include "shill/mock_dhcp_provider.h"
#include "shill/mock_manager.h"
#include "shill/mock_supplicant_interface_proxy.h"
#include "shill/mock_supplicant_process_proxy.h"
@@ -106,6 +111,11 @@
supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
supplicant_interface_proxy_(
new NiceMock<MockSupplicantInterfaceProxy>(wifi_)),
+ dhcp_config_(new MockDHCPConfig(&control_interface_,
+ &dispatcher_,
+ &dhcp_provider_,
+ kDeviceName,
+ &glib_)),
proxy_factory_(this) {
ProxyFactory::set_factory(&proxy_factory_);
::testing::DefaultValue< ::DBus::Path>::Set("/default/path");
@@ -117,6 +127,10 @@
wifi_->Stop();
}
+ virtual void SetUp() {
+ wifi_->set_dhcp_provider(&dhcp_provider_);
+ }
+
protected:
class TestProxyFactory : public ProxyFactory {
public:
@@ -156,11 +170,17 @@
void InitiateConnect(WiFiService *service) {
wifi_->ConnectTo(service);
}
+ bool IsLinkUp() {
+ return wifi_->link_up_;
+ }
void ReportBSS(const ::DBus::Path &bss_path,
const string &ssid,
const string &bssid,
int16_t signal_strength,
const char *mode);
+ void ReportLinkUp() {
+ wifi_->LinkEvent(IFF_LOWER_UP, IFF_LOWER_UP);
+ }
void ReportScanDone() {
wifi_->ScanDoneTask();
}
@@ -181,6 +201,7 @@
private:
NiceMockControl control_interface_;
+ MockGLib glib_;
MockManager manager_;
WiFiRefPtr wifi_;
@@ -194,6 +215,8 @@
scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_;
scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
+ MockDHCPProvider dhcp_provider_;
+ scoped_refptr<MockDHCPConfig> dhcp_config_;
private:
TestProxyFactory proxy_factory_;
@@ -329,7 +352,16 @@
.WillOnce(Return(fake_path));
EXPECT_CALL(supplicant_interface_proxy, SelectNetwork(fake_path));
InitiateConnect(service);
+ EXPECT_EQ(static_cast<Service *>(service),
+ wifi()->selected_service_.get());
}
}
+TEST_F(WiFiMainTest, LinkEvent) {
+ EXPECT_FALSE(IsLinkUp());
+ EXPECT_CALL(dhcp_provider_, CreateConfig(_)).
+ WillOnce(Return(dhcp_config_));
+ ReportLinkUp();
+}
+
} // namespace shill