shill: Add a command line option that controls the default technology order
This can be used to configure a preference for a particular network on a given
device. For example, a device may want to use the mobile network for all
traffic even if an open wifi network is available.
BUG=chromium:453607
TEST=Added the flag via /etc/init/shill.override and confirmed that dbus GetServiceOrder returned the new order
Change-Id: Ifac0baa4feeaae4a780d4d74f2bd195b4e4dd31d
Reviewed-on: https://chromium-review.googlesource.com/248610
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Jason Simmons <jsimmons@chromium.org>
Commit-Queue: Jason Simmons <jsimmons@chromium.org>
diff --git a/manager.cc b/manager.cc
index 37ebdc9..166b326 100644
--- a/manager.cc
+++ b/manager.cc
@@ -100,7 +100,8 @@
GLib *glib,
const string &run_directory,
const string &storage_directory,
- const string &user_storage_directory)
+ const string &user_storage_directory,
+ const vector<Technology::Identifier> &default_technology_order)
: dispatcher_(dispatcher),
run_path_(FilePath(run_directory)),
storage_path_(FilePath(storage_directory)),
@@ -195,13 +196,8 @@
&Manager::UninitializedTechnologies);
store_.RegisterBool(kWakeOnLanEnabledProperty, &is_wake_on_lan_enabled_);
- // Set default technology order "by hand", to avoid invoking side
- // effects of SetTechnologyOrder.
- technology_order_.push_back(Technology::IdentifierFromName(kTypeVPN));
- technology_order_.push_back(Technology::IdentifierFromName(kTypeEthernet));
- technology_order_.push_back(Technology::IdentifierFromName(kTypeWifi));
- technology_order_.push_back(Technology::IdentifierFromName(kTypeWimax));
- technology_order_.push_back(Technology::IdentifierFromName(kTypeCellular));
+ // Do not invoke SetTechnologyOrder here because of its side effects.
+ technology_order_ = default_technology_order;
UpdateProviderMapping();
diff --git a/manager.h b/manager.h
index f73ee4e..1c99b7e 100644
--- a/manager.h
+++ b/manager.h
@@ -89,7 +89,8 @@
GLib *glib,
const std::string &run_directory,
const std::string &storage_directory,
- const std::string &user_storage_directory);
+ const std::string &user_storage_directory,
+ const std::vector<Technology::Identifier> &default_technology_order);
virtual ~Manager();
void AddDeviceToBlackList(const std::string &device_name);
diff --git a/manager_unittest.cc b/manager_unittest.cc
index 8897952..f9b9e16 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -617,7 +617,8 @@
&glib,
run_path(),
storage_path(),
- string());
+ string(),
+ default_technology_order());
ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
ASSERT_TRUE(profile.get());
AdoptProfile(&manager, profile);
@@ -670,7 +671,8 @@
&glib,
run_path(),
storage_path(),
- string());
+ string(),
+ default_technology_order());
ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
ASSERT_TRUE(profile.get());
AdoptProfile(&manager, profile);
@@ -703,7 +705,8 @@
&glib,
run_path(),
storage_path(),
- string());
+ string(),
+ default_technology_order());
ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
ASSERT_TRUE(profile.get());
AdoptProfile(&manager, profile);
@@ -805,7 +808,8 @@
glib(),
run_path(),
storage_path(),
- string());
+ string(),
+ default_technology_order());
scoped_refptr<MockService> s2(new MockService(control_interface(),
dispatcher(),
metrics(),
@@ -929,7 +933,8 @@
&glib,
run_path(),
storage_path(),
- temp_dir.path().value());
+ temp_dir.path().value(),
+ default_technology_order());
// Invalid name should be rejected.
EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, ""));
@@ -969,7 +974,8 @@
&glib,
run_path(),
storage_path(),
- temp_dir.path().value());
+ temp_dir.path().value(),
+ default_technology_order());
vector<ProfileRefPtr> &profiles = GetProfiles(&manager);
// Pushing an invalid profile should fail.
@@ -1145,7 +1151,8 @@
&glib,
run_path(),
storage_path(),
- temp_dir.path().value());
+ temp_dir.path().value(),
+ default_technology_order());
const char kProfile0[] = "profile0";
FilePath profile_path(
@@ -1259,7 +1266,8 @@
&glib,
run_path(),
storage_path(),
- temp_dir.path().value());
+ temp_dir.path().value(),
+ default_technology_order());
const char kProfile0[] = "profile0";
FilePath profile_path(
@@ -4310,7 +4318,8 @@
&glib,
run_path(),
storage_path(),
- temp_dir.path().value());
+ temp_dir.path().value(),
+ default_technology_order());
// Can't use |wifi_provider_|, because it's owned by the Manager
// object in the fixture.
MockWiFiProvider *wifi_provider = new NiceMock<MockWiFiProvider>();
@@ -4366,7 +4375,8 @@
&glib,
run_path(),
temp_dir.path().value(),
- temp_dir.path().value()));
+ temp_dir.path().value(),
+ default_technology_order()));
manager->InitializeProfiles();
EXPECT_EQ(PortalDetector::kDefaultCheckPortalList,
manager->props_.check_portal_list);
@@ -4393,7 +4403,8 @@
&glib,
run_path(),
temp_dir.path().value(),
- temp_dir.path().value()));
+ temp_dir.path().value(),
+ default_technology_order()));
manager->InitializeProfiles();
EXPECT_EQ(kCustomCheckPortalList, manager->props_.check_portal_list);
@@ -4406,7 +4417,8 @@
&glib,
run_path(),
temp_dir.path().value(),
- temp_dir.path().value()));
+ temp_dir.path().value(),
+ default_technology_order()));
manager->InitializeProfiles();
EXPECT_EQ(PortalDetector::kDefaultCheckPortalList,
manager->props_.check_portal_list);
@@ -4425,7 +4437,8 @@
&glib,
run_path(),
temp_dir.path().value(),
- temp_dir.path().value()));
+ temp_dir.path().value(),
+ default_technology_order()));
ScopedMockLog log;
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
diff --git a/mock_manager.cc b/mock_manager.cc
index 907dc6d..e142337 100644
--- a/mock_manager.cc
+++ b/mock_manager.cc
@@ -4,8 +4,11 @@
#include "shill/mock_manager.h"
+#include <vector>
+
#include <gmock/gmock.h>
+using std::vector;
using testing::Invoke;
namespace shill {
@@ -14,7 +17,8 @@
EventDispatcher *dispatcher,
Metrics *metrics,
GLib *glib)
- : Manager(control_interface, dispatcher, metrics, glib, "", "", ""),
+ : Manager(control_interface, dispatcher, metrics, glib, "", "", "",
+ vector<Technology::Identifier>()),
mock_device_info_(nullptr) {
EXPECT_CALL(*this, device_info())
.WillRepeatedly(Invoke(this, &MockManager::mock_device_info));
diff --git a/property_store_unittest.cc b/property_store_unittest.cc
index 7de166c..30be06f 100644
--- a/property_store_unittest.cc
+++ b/property_store_unittest.cc
@@ -79,13 +79,19 @@
invalid_prop_(kErrorResultInvalidProperty),
path_(dir_.CreateUniqueTempDir() ? dir_.path().value() : ""),
metrics_(dispatcher()),
+ default_technology_order_{Technology::kVPN,
+ Technology::kEthernet,
+ Technology::kWifi,
+ Technology::kWiMax,
+ Technology::kCellular},
manager_(control_interface(),
dispatcher(),
metrics(),
glib(),
run_path(),
storage_path(),
- string()) {
+ string(),
+ default_technology_order()) {
}
PropertyStoreTest::~PropertyStoreTest() {}
diff --git a/property_store_unittest.h b/property_store_unittest.h
index 6b1ee05..c63175f 100644
--- a/property_store_unittest.h
+++ b/property_store_unittest.h
@@ -181,6 +181,9 @@
EventDispatcher *dispatcher() { return &dispatcher_; }
MockGLib *glib() { return &glib_; }
MockMetrics *metrics() { return &metrics_; }
+ const std::vector<Technology::Identifier> &default_technology_order() {
+ return default_technology_order_;
+ }
const std::string &run_path() const { return path_; }
const std::string &storage_path() const { return path_; }
@@ -199,6 +202,7 @@
EventDispatcher dispatcher_;
testing::NiceMock<MockMetrics> metrics_;
MockGLib glib_;
+ const std::vector<Technology::Identifier> default_technology_order_;
Manager manager_;
};
diff --git a/shill_daemon.cc b/shill_daemon.cc
index ab82567..00cf307 100644
--- a/shill_daemon.cc
+++ b/shill_daemon.cc
@@ -23,6 +23,7 @@
using base::Bind;
using base::Unretained;
using std::string;
+using std::vector;
namespace shill {
@@ -32,7 +33,8 @@
}
-Daemon::Daemon(Config *config, ControlInterface *control)
+Daemon::Daemon(Config *config, ControlInterface *control,
+ const vector<Technology::Identifier> &default_technology_order)
: config_(config),
control_(control),
metrics_(new Metrics(&dispatcher_)),
@@ -47,7 +49,8 @@
&glib_,
config->GetRunDirectory(),
config->GetStorageDirectory(),
- config->GetUserStorageDirectory())),
+ config->GetUserStorageDirectory(),
+ default_technology_order)),
callback80211_metrics_(metrics_.get()) {
}
diff --git a/shill_daemon.h b/shill_daemon.h
index c886192..d2cbf19 100644
--- a/shill_daemon.h
+++ b/shill_daemon.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "shill/control_interface.h"
#include "shill/event_dispatcher.h"
@@ -28,7 +29,8 @@
class Daemon {
public:
- Daemon(Config *config, ControlInterface *control);
+ Daemon(Config *config, ControlInterface *control,
+ const std::vector<Technology::Identifier> &default_technology_order);
~Daemon();
void AddDeviceToBlackList(const std::string &device_name);
diff --git a/shill_main.cc b/shill_main.cc
index c20f6fa..4d98f06 100644
--- a/shill_main.cc
+++ b/shill_main.cc
@@ -19,6 +19,7 @@
#include <chromeos/syslog_logging.h>
#include "shill/dbus_control.h"
+#include "shill/error.h"
#include "shill/glib_io_handler_factory.h"
#include "shill/logging.h"
#include "shill/net/io_handler_factory_container.h"
@@ -44,6 +45,8 @@
// Remote service can instruct Shill to manage/unmanage devices through
// org.chromium.flimflam.Manager's ClaimInterface/ReleaseInterface APIs.
static const char kPassiveMode[] = "passive-mode";
+// Default priority order of the technologies.
+static const char kDefaultTechnologyOrder[] = "default-technology-order";
// Flag that causes shill to show the help message and exit.
static const char kHelp[] = "help";
@@ -65,7 +68,9 @@
" --portal-list=technology1,technology2\n"
" Specify technologies to perform portal detection on at startup.\n"
" --passive-mode\n"
- " Do not manage any devices by default\n";
+ " Do not manage any devices by default\n"
+ " --default-technology-order=technology1,technology2\n"
+ " Specify the default priority order of the technologies.\n";
} // namespace switches
namespace {
@@ -153,10 +158,34 @@
shill::DBusControl* dbus_control = new shill::DBusControl();
dbus_control->Init();
+ vector<shill::Technology::Identifier> technology_order;
+ if (cl->HasSwitch(switches::kDefaultTechnologyOrder)) {
+ shill::Error error;
+ string order_flag = cl->GetSwitchValueASCII(
+ switches::kDefaultTechnologyOrder);
+ if (!shill::Technology::GetTechnologyVectorFromString(
+ order_flag, &technology_order, &error)) {
+ LOG(ERROR) << "Invalid default technology order: [" << order_flag
+ << "] Error: " << error.message();
+ }
+ }
+ if (technology_order.empty()) {
+ technology_order.push_back(
+ shill::Technology::IdentifierFromName(shill::kTypeVPN));
+ technology_order.push_back(
+ shill::Technology::IdentifierFromName(shill::kTypeEthernet));
+ technology_order.push_back(
+ shill::Technology::IdentifierFromName(shill::kTypeWifi));
+ technology_order.push_back(
+ shill::Technology::IdentifierFromName(shill::kTypeWimax));
+ technology_order.push_back(
+ shill::Technology::IdentifierFromName(shill::kTypeCellular));
+ }
+
shill::Config config;
// Passes ownership of dbus_control.
- shill::Daemon daemon(&config, dbus_control);
+ shill::Daemon daemon(&config, dbus_control, technology_order);
if (cl->HasSwitch(switches::kDeviceBlackList)) {
vector<string> device_list;
diff --git a/shill_unittest.cc b/shill_unittest.cc
index 96e7ad7..b1fb375 100644
--- a/shill_unittest.cc
+++ b/shill_unittest.cc
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <memory>
+#include <vector>
#include <base/bind.h>
#include <base/cancelable_callback.h>
@@ -33,6 +34,7 @@
using base::CancelableClosure;
using base::Unretained;
using base::WeakPtrFactory;
+using std::vector;
using ::testing::Expectation;
using ::testing::Gt;
@@ -183,7 +185,8 @@
class ShillDaemonTest : public Test {
public:
ShillDaemonTest()
- : daemon_(&config_, new MockControl()), // Passes ownership.
+ : daemon_(&config_, new MockControl(),
+ vector<Technology::Identifier>()), // Passes ownership.
metrics_(new MockMetrics(&daemon_.dispatcher_)),
manager_(new MockManager(daemon_.control_.get(),
&daemon_.dispatcher_,