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/09/24 20:03:03 UTC

git commit: Added support for getting socket diagnosis information.

Repository: mesos
Updated Branches:
  refs/heads/master 896ec461e -> 5d46ce9b1


Added support for getting socket diagnosis information.

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


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

Branch: refs/heads/master
Commit: 5d46ce9b1df0de14caaf803bdb8a335dce98e58a
Parents: 896ec46
Author: Chi Zhang <ch...@gmail.com>
Authored: Wed Sep 24 10:44:38 2014 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Sep 24 10:53:18 2014 -0700

----------------------------------------------------------------------
 configure.ac                              |  11 +++
 src/Makefile.am                           |   2 +
 src/linux/routing/diagnosis/diagnosis.cpp |  87 ++++++++++++++++++
 src/linux/routing/diagnosis/diagnosis.hpp | 121 +++++++++++++++++++++++++
 src/linux/routing/internal.hpp            |  14 ++-
 src/tests/routing_tests.cpp               |  18 ++++
 6 files changed, 249 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5d46ce9b/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index da61c29..86d448c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -665,6 +665,17 @@ http://www.infradead.org/~tgr/libnl/
 -------------------------------------------------------------------
   ])])
 
+  # Check for libnl-idiag-3 (both headers and libraries).
+  AC_CHECK_LIB([nl-idiag-3], [idiagnl_msg_alloc_cache], [],
+               [AC_MSG_ERROR([cannot find libnl-idiag-3
+-------------------------------------------------------------------
+We need libnl-idiag-3 for building network isolator!
+
+Please install libnl3 (version 3.2.24 or higher):
+http://www.infradead.org/~tgr/libnl/
+-------------------------------------------------------------------
+  ])])
+
   # TODO(jieyu): Automatically detect the location where the libnl
   # headers are installed.
   LIBNL_CFLAGS=-I/usr/include/libnl3

http://git-wip-us.apache.org/repos/asf/mesos/blob/5d46ce9b/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b973e5..b821a3b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -348,6 +348,7 @@ if WITH_NETWORK_ISOLATOR
   libmesos_no_3rdparty_la_SOURCES +=					\
 	linux/routing/route.cpp						\
 	linux/routing/utils.cpp						\
+	linux/routing/diagnosis/diagnosis.cpp				\
 	linux/routing/filter/arp.cpp					\
 	linux/routing/filter/icmp.cpp					\
 	linux/routing/filter/ip.cpp					\
@@ -359,6 +360,7 @@ if WITH_NETWORK_ISOLATOR
 	linux/routing/internal.hpp					\
 	linux/routing/route.hpp						\
 	linux/routing/utils.hpp						\
+	linux/routing/diagnosis/diagnosis.hpp				\
 	linux/routing/filter/action.hpp					\
 	linux/routing/filter/arp.hpp					\
 	linux/routing/filter/filter.hpp					\

http://git-wip-us.apache.org/repos/asf/mesos/blob/5d46ce9b/src/linux/routing/diagnosis/diagnosis.cpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/diagnosis/diagnosis.cpp b/src/linux/routing/diagnosis/diagnosis.cpp
new file mode 100644
index 0000000..36e4e2d
--- /dev/null
+++ b/src/linux/routing/diagnosis/diagnosis.cpp
@@ -0,0 +1,87 @@
+/**
+ * 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 <netlink/cache.h>
+#include <netlink/errno.h>
+
+#include <netlink/idiag/msg.h>
+
+#include <stout/error.hpp>
+#include <stout/try.hpp>
+
+#include "linux/routing/internal.hpp"
+
+#include "linux/routing/diagnosis/diagnosis.hpp"
+
+using namespace std;
+
+namespace routing {
+namespace diagnosis {
+
+namespace socket {
+
+static Option<net::IP> IP(nl_addr* _ip)
+{
+  Option<net::IP> result;
+  if (_ip != NULL && nl_addr_get_len(_ip) != 0) {
+    struct in_addr* addr = (struct in_addr*) nl_addr_get_binary_addr(_ip);
+
+    result = net::IP(ntohl(addr->s_addr));
+  }
+
+  return result;
+}
+
+
+Try<vector<Info> > infos(int family, State states)
+{
+  Try<Netlink<struct nl_sock> > sock = routing::socket(NETLINK_INET_DIAG);
+  if (sock.isError()) {
+    return Error(sock.error());
+  }
+
+  struct nl_cache* c = NULL;
+  int err = idiagnl_msg_alloc_cache(sock.get().get(), family, states, &c);
+  if (err != 0) {
+    return Error(nl_geterror(err));
+  }
+
+  Netlink<struct nl_cache> cache(c);
+
+  vector<Info> results;
+  for (struct nl_object* o = nl_cache_get_first(cache.get());
+       o != NULL; o = nl_cache_get_next(o)) {
+    struct idiagnl_msg* msg = (struct idiagnl_msg*)o;
+
+    results.push_back(Info(
+        idiagnl_msg_get_family(msg),
+        (State) idiagnl_msg_get_state(msg),
+        idiagnl_msg_get_sport(msg),
+        idiagnl_msg_get_dport(msg),
+        IP(idiagnl_msg_get_src(msg)),
+        IP(idiagnl_msg_get_dst(msg)),
+        idiagnl_msg_get_tcpinfo(msg)));
+  }
+
+  return results;
+}
+
+} // namespace socket {
+
+} // namespace diagnosis {
+} // namespace routing {

http://git-wip-us.apache.org/repos/asf/mesos/blob/5d46ce9b/src/linux/routing/diagnosis/diagnosis.hpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/diagnosis/diagnosis.hpp b/src/linux/routing/diagnosis/diagnosis.hpp
new file mode 100644
index 0000000..aa1b3a3
--- /dev/null
+++ b/src/linux/routing/diagnosis/diagnosis.hpp
@@ -0,0 +1,121 @@
+/**
+ * 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_DIAGNOSIS_DIAGNOSIS_HPP__
+#define __LINUX_ROUTING_DIAGNOSIS_DIAGNOSIS_HPP__
+
+#include <sys/socket.h> // For protocol families, e.g., AF_INET6 is IPv6.
+
+#include <netinet/tcp.h> // For tcp_info.
+
+#include <vector>
+
+#include <stout/net.hpp>
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+namespace routing {
+namespace diagnosis {
+
+namespace socket {
+
+// The connection state of a socket.
+// TODO(chzhcn): libnl3-idiag still uses the old idiag kernel API,
+// which only supports TCP sockets. When it moves to the newer API,
+// consider changing this to a per-family state structure.
+enum State
+{
+  UNKNOWN,
+  ESTABLISHED,
+  SYN_SENT,
+  SYN_RECV,
+  FIN_WAIT1,
+  FIN_WAIT2,
+  TIME_WAIT,
+  CLOSE,
+  CLOSE_WAIT,
+  LAST_ACK,
+  LISTEN,
+  CLOSING,
+  MAX,
+  ALL = (1 << MAX) - 1
+};
+
+
+// The diagnosis information of a socket. We only included a few
+// members of 'struct idiagnl_msg' from libnl3-idiag, but more could
+// be added later on.
+class Info
+{
+public:
+  Info(int _family,
+       State _state,
+       const Option<uint16_t>& _sourcePort,
+       const Option<uint16_t>& _destinationPort,
+       const Option<net::IP>& _sourceIP,
+       const Option<net::IP>& _destinationIP,
+       const Option<struct tcp_info>& _tcpInfo)
+    : family_(_family),
+      state_(_state),
+      sourcePort_(_sourcePort),
+      destinationPort_(_destinationPort),
+      sourceIP_(_sourceIP),
+      destinationIP_(_destinationIP),
+      tcpInfo_(_tcpInfo) {}
+
+  int family() const { return family_; }
+  State state() const { return state_; }
+  const Option<uint16_t>& sourcePort() const { return sourcePort_; }
+  const Option<uint16_t>& destinationPort() const { return destinationPort_; }
+  const Option<net::IP>& sourceIP() const { return sourceIP_; }
+  const Option<net::IP>& destinationIP() const { return destinationIP_; }
+  const Option<struct tcp_info>& tcpInfo() const { return tcpInfo_; }
+
+private:
+  int family_;
+  State state_;
+
+  // sourcePort, destinationPort, sourceIP and destinationIP should
+  // all be present because this version of kernel API that libnl3
+  // uses can only return TCP sockets. We leave them as optional here
+  // because future support of other families could leave them as
+  // empty values.
+  Option<uint16_t> sourcePort_;
+  Option<uint16_t> destinationPort_;
+  Option<net::IP> sourceIP_;
+  Option<net::IP> destinationIP_;
+
+  // tcp_info is included in the kernel header files so we expose it
+  // directly.
+  Option<struct tcp_info> tcpInfo_;
+};
+
+
+// Return a list of socket information that matches the given protocol
+// family and socket state.
+// NOTE: 'family' is actually igored here because the older kernel
+// idiag API libnl3 uses only supports TCP and ingores this value. We
+// keep it here to follow libnl3-idiag's suit.
+Try<std::vector<Info> > infos(int familiy, State states);
+
+} // namespace socket {
+
+} // namespace diagnosis {
+} // namespace routing {
+
+#endif // __LINUX_ROUTING_DIAGNOSIS_DIAGNOSIS_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/5d46ce9b/src/linux/routing/internal.hpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/internal.hpp b/src/linux/routing/internal.hpp
index dca0dc5..87a539b 100644
--- a/src/linux/routing/internal.hpp
+++ b/src/linux/routing/internal.hpp
@@ -24,6 +24,8 @@
 #include <netlink/netlink.h>
 #include <netlink/socket.h>
 
+#include <netlink/idiag/msg.h>
+
 #include <netlink/route/classifier.h>
 #include <netlink/route/link.h>
 #include <netlink/route/qdisc.h>
@@ -44,6 +46,7 @@ inline void cleanup(struct nl_sock* sock) { nl_socket_free(sock); }
 inline void cleanup(struct rtnl_cls* cls) { rtnl_cls_put(cls); }
 inline void cleanup(struct rtnl_link* link) { rtnl_link_put(link); }
 inline void cleanup(struct rtnl_qdisc* qdisc) { rtnl_qdisc_put(qdisc); }
+inline void cleanup(struct idiagnl_msg* msg) { idiagnl_msg_put(msg); }
 
 
 // A helper class for managing netlink objects (e.g., rtnl_link,
@@ -81,8 +84,11 @@ private:
 
 
 // Returns a netlink socket for communicating with the kernel. This
-// socket is needed for most of the operations.
-inline Try<Netlink<struct nl_sock> > socket()
+// socket is needed for most of the operations. The default protocol
+// of the netlink socket is NETLINK_ROUTE, but you can optionally
+// provide a different one.
+// TODO(chzhcn): Consider renaming 'routing' to 'netlink'.
+inline Try<Netlink<struct nl_sock> > socket(int protocol = NETLINK_ROUTE)
 {
   Try<Nothing> checking = check();
   if (checking.isError()) {
@@ -96,10 +102,10 @@ inline Try<Netlink<struct nl_sock> > socket()
 
   Netlink<struct nl_sock> sock(s);
 
-  int err = nl_connect(sock.get(), NETLINK_ROUTE);
+  int err = nl_connect(sock.get(), protocol);
   if (err != 0) {
     return Error(
-        "Failed to connect to routing netlink protocol: " +
+        "Failed to connect to netlink protocol: " +
         std::string(nl_geterror(err)));
   }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5d46ce9b/src/tests/routing_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/routing_tests.cpp b/src/tests/routing_tests.cpp
index 10730ad..35bdf8f 100644
--- a/src/tests/routing_tests.cpp
+++ b/src/tests/routing_tests.cpp
@@ -38,6 +38,8 @@
 #include "linux/routing/route.hpp"
 #include "linux/routing/utils.hpp"
 
+#include "linux/routing/diagnosis/diagnosis.hpp"
+
 #include "linux/routing/filter/arp.hpp"
 #include "linux/routing/filter/icmp.hpp"
 #include "linux/routing/filter/ip.hpp"
@@ -228,6 +230,22 @@ TEST_F(RoutingTest, Lo)
 }
 
 
+TEST_F(RoutingTest, INETSockets)
+{
+  Try<vector<diagnosis::socket::Info> > infos =
+    diagnosis::socket::infos(AF_INET, diagnosis::socket::State::ALL);
+
+  EXPECT_SOME(infos);
+
+  foreach (const diagnosis::socket::Info& info, infos.get()) {
+    // Both source and destination IPs should be present since
+    // 'AF_INET' is asked for.
+    EXPECT_SOME(info.sourceIP());
+    EXPECT_SOME(info.destinationIP());
+  }
+}
+
+
 TEST_F(RoutingVethTest, ROOT_LinkCreate)
 {
   ASSERT_SOME(link::create(TEST_VETH_LINK, TEST_PEER_LINK, None()));