You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2014/05/15 03:21:38 UTC

[8/9] git commit: Added API for getting the default gateway.

Added API for getting the default gateway.

Review: https://reviews.apache.org/r/20347


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/19f643aa
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/19f643aa
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/19f643aa

Branch: refs/heads/master
Commit: 19f643aa5b84f3542cd92b0d84bef543c55b9b52
Parents: d6bcfa9
Author: Jie Yu <yu...@gmail.com>
Authored: Mon Apr 14 18:23:45 2014 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed May 14 17:38:43 2014 -0700

----------------------------------------------------------------------
 src/Makefile.am             |   2 +
 src/linux/routing/route.cpp | 136 +++++++++++++++++++++++++++++++++++++++
 src/linux/routing/route.hpp |  65 +++++++++++++++++++
 src/tests/routing_tests.cpp |  11 ++++
 4 files changed, 214 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/19f643aa/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index ce97f1b..ae576c5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -268,6 +268,7 @@ endif
 
 if WITH_NETWORK_ISOLATOR
   libmesos_no_3rdparty_la_SOURCES +=					\
+	linux/routing/route.cpp						\
 	linux/routing/utils.cpp						\
 	linux/routing/link/link.cpp					\
 	linux/routing/filter/arp.cpp					\
@@ -278,6 +279,7 @@ if WITH_NETWORK_ISOLATOR
 
   libmesos_no_3rdparty_la_SOURCES +=					\
 	linux/routing/internal.hpp					\
+	linux/routing/route.hpp						\
 	linux/routing/utils.hpp						\
 	linux/routing/filter/action.hpp					\
 	linux/routing/filter/arp.hpp					\

http://git-wip-us.apache.org/repos/asf/mesos/blob/19f643aa/src/linux/routing/route.cpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/route.cpp b/src/linux/routing/route.cpp
new file mode 100644
index 0000000..6e3ec0f
--- /dev/null
+++ b/src/linux/routing/route.cpp
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <linux/rtnetlink.h>
+
+#include <netinet/in.h>
+
+#include <netlink/addr.h>
+#include <netlink/cache.h>
+#include <netlink/errno.h>
+#include <netlink/object.h>
+#include <netlink/socket.h>
+
+#include <netlink/route/route.h>
+
+#include <glog/logging.h>
+
+#include <stout/error.hpp>
+#include <stout/foreach.hpp>
+#include <stout/none.hpp>
+#include <stout/stringify.hpp>
+
+#include "linux/routing/internal.hpp"
+#include "linux/routing/route.hpp"
+
+#include "linux/routing/link/link.hpp"
+
+using std::string;
+using std::vector;
+
+namespace routing {
+namespace route {
+
+Try<vector<Rule> > table()
+{
+  Try<Netlink<struct nl_sock> > sock = routing::socket();
+  if (sock.isError()) {
+    return Error(sock.error());
+  }
+
+  // Dump all the routes (for IPv4) from kernel.
+  struct nl_cache* c = NULL;
+  int err = rtnl_route_alloc_cache(sock.get().get(), AF_INET, 0, &c);
+  if (err != 0) {
+    return Error(nl_geterror(err));
+  }
+
+  Netlink<struct nl_cache> cache(c);
+
+  vector<Rule> results;
+
+  // Scan the routes and look for entries in the main routing table.
+  for (struct nl_object* o = nl_cache_get_first(cache.get());
+       o != NULL; o = nl_cache_get_next(o)) {
+    struct rtnl_route* route = (struct rtnl_route*) o;
+
+    // TODO(jieyu): Currently, we assume each route in the routing
+    // table has only one hop (which is true in most environments).
+    if (rtnl_route_get_table(route) == RT_TABLE_MAIN &&
+        rtnl_route_get_nnexthops(route) == 1) {
+      CHECK_EQ(AF_INET, rtnl_route_get_family(route));
+
+      // Get the destination IP if exists.
+      Option<net::IP> destination;
+      struct nl_addr* dst = rtnl_route_get_dst(route);
+      if (dst != NULL && nl_addr_get_len(dst) != 0) {
+        struct in_addr* addr = (struct in_addr*) nl_addr_get_binary_addr(dst);
+
+        // Calculate the netmask based on the prefix length.
+        CHECK_GE(32u, nl_addr_get_prefixlen(dst));
+        uint32_t netmask = 0xffffffff << (32 - nl_addr_get_prefixlen(dst));
+
+        destination = net::IP(ntohl(addr->s_addr), netmask);
+      }
+
+      // Get the default gateway if exists.
+      Option<net::IP> gateway;
+      struct rtnl_nexthop* hop = rtnl_route_nexthop_n(route, 0);
+      struct nl_addr* gw = rtnl_route_nh_get_gateway(CHECK_NOTNULL(hop));
+      if (gw != NULL && nl_addr_get_len(gw) != 0) {
+        struct in_addr* addr = (struct in_addr*) nl_addr_get_binary_addr(gw);
+        gateway = net::IP(ntohl(addr->s_addr));
+      }
+
+      // Get the destination link.
+      int index = rtnl_route_nh_get_ifindex(hop);
+      Result<string> link = link::name(index);
+      if (link.isError()) {
+        return Error("Failed to get the link name: " + link.error());
+      } else if (link.isNone()) {
+        return Error("Link of index " + stringify(index) + " is not found");
+      }
+
+      results.push_back(Rule(destination, gateway, link.get()));
+    }
+  }
+
+  return results;
+}
+
+
+Result<net::IP> defaultGateway()
+{
+  Try<vector<Rule> > rules = table();
+  if (rules.isError()) {
+    return Error("Failed to get the routing table: " + rules.error());
+  }
+
+  foreach (const Rule& rule, rules.get()) {
+    if (rule.destination().isNone() && rule.gateway().isSome()) {
+      return rule.gateway().get();
+    }
+  }
+
+  return None();
+}
+
+} // namespace route
+} // namespace routing

http://git-wip-us.apache.org/repos/asf/mesos/blob/19f643aa/src/linux/routing/route.hpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/route.hpp b/src/linux/routing/route.hpp
new file mode 100644
index 0000000..435b981
--- /dev/null
+++ b/src/linux/routing/route.hpp
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LINUX_ROUTING_ROUTE_HPP__
+#define __LINUX_ROUTING_ROUTE_HPP__
+
+#include <string>
+#include <vector>
+
+#include <stout/net.hpp>
+#include <stout/option.hpp>
+#include <stout/result.hpp>
+#include <stout/try.hpp>
+
+namespace routing {
+namespace route {
+
+// Represents a rule in the routing table (for IPv4).
+class Rule
+{
+public:
+  Rule(const Option<net::IP>& _destination,
+       const Option<net::IP>& _gateway,
+       const std::string& _link)
+    : destination_(_destination),
+      gateway_(_gateway),
+      link_(_link) {}
+
+  const Option<net::IP>& destination() const { return destination_; }
+  const Option<net::IP>& gateway() const { return gateway_; }
+  const std::string& link() const { return link_; }
+
+private:
+  Option<net::IP> destination_;
+  Option<net::IP> gateway_;
+  std::string link_;
+};
+
+
+// Returns the main routing table of this host.
+Try<std::vector<Rule> > table();
+
+
+// Returns the default gateway of this host.
+Result<net::IP> defaultGateway();
+
+} // namespace route
+} // namespace routing
+
+#endif // __LINUX_ROUTING_ROUTE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/19f643aa/src/tests/routing_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/routing_tests.cpp b/src/tests/routing_tests.cpp
index 5650fca..aca88dc 100644
--- a/src/tests/routing_tests.cpp
+++ b/src/tests/routing_tests.cpp
@@ -31,6 +31,7 @@
 #include <stout/hashmap.hpp>
 #include <stout/net.hpp>
 
+#include "linux/routing/route.hpp"
 #include "linux/routing/utils.hpp"
 
 #include "linux/routing/filter/arp.hpp"
@@ -128,6 +129,16 @@ TEST_F(RoutingTest, PortRange)
 }
 
 
+TEST_F(RoutingTest, RouteTable)
+{
+  Try<vector<route::Rule> > table = route::table();
+  EXPECT_SOME(table);
+
+  Result<net::IP> gateway = route::defaultGateway();
+  EXPECT_FALSE(gateway.isError());
+}
+
+
 TEST_F(RoutingTest, LinkIndex)
 {
   Try<set<string> > links = net::links();