shill: Assign unique metrics to non-default interfaces

Assign a metric based on the interface index to routes
for interfaces that are not default.  As a result even
if the gateway address is the same (e.g, if you're connected
to a home AP via both wireless and wired) that the routes
do not conflict with each other.

BUG=chromium-os:23917
TEST=Manual: As above, connect to a home AP over Ethernet
and WiFi, and ensure that both gateway routes appear.

Change-Id: I85ffad74ec53dda535578367242114b30846b7ac
Reviewed-on: https://gerrit.chromium.org/gerrit/12651
Commit-Ready: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/connection.cc b/connection.cc
index 847ac4d..25291b5 100644
--- a/connection.cc
+++ b/connection.cc
@@ -19,7 +19,7 @@
 // static
 const uint32 Connection::kDefaultMetric = 1;
 // static
-const uint32 Connection::kNonDefaultMetric = 10;
+const uint32 Connection::kNonDefaultMetricBase = 10;
 
 Connection::Connection(int interface_index,
                        const std::string& interface_name,
@@ -61,8 +61,8 @@
 
   rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast);
 
-  uint32 metric = is_default_ ? kDefaultMetric : kNonDefaultMetric;
-  routing_table_->SetDefaultRoute(interface_index_, config, metric);
+  routing_table_->SetDefaultRoute(interface_index_, config,
+                                  GetMetric(is_default_));
 
   // Save a copy of the last non-null DNS config
   if (!config->properties().dns_servers.empty()) {
@@ -81,8 +81,7 @@
     return;
   }
 
-  routing_table_->SetDefaultMetric(interface_index_,
-      is_default ? kDefaultMetric : kNonDefaultMetric);
+  routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
 
   if (is_default) {
     resolver_->SetDNSFromLists(dns_servers_, dns_domain_search_);
@@ -91,4 +90,11 @@
   is_default_ = is_default;
 }
 
+uint32 Connection::GetMetric(bool is_default) {
+  // If this is not the default route, assign a metric based on the interface
+  // index.  This way all non-default routes (even to the same gateway IP) end
+  // up with unique metrics so they do not collide.
+  return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
+}
+
 }  // namespace shill