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()));