Feature #3353
closedNetworkMonitor: emit fine-grained signals when the state of a network interface changes
Added by Andrea Tosatto almost 9 years ago. Updated over 7 years ago.
100%
Description
Save the status of every system network interface and notify if there are any link or address changes in one of them. For example:
eth0
is unplugged -> emit an interface removal signalwlan0
is down -> emit an internal state change signalwlan1
has a new IP address -> emit an IP address addition signal
Updated by Andrea Tosatto almost 9 years ago
- Status changed from New to In Progress
The idea is to add a fine grained monitoring of all the network interfaces in the ndn::util::NetworkMonitor class.
Save the list of all the networks interfaces using a map would be easier to answer requests about the state of one or more interfaces. Every map element will be of type NetworkInterfaceInfo declared inside nfd::NetworkInterface. This is a class used in NFD and useful to store a single network interface state. The NetworkInterfaceInfo will be copied inside NetworkMonitor and later can be removed from NFD.
NetworkMonitor will update asynchronously the map and send a signal according to the event.
As part of this task I'll implement the class only for linux and will rely on rtnetlink notifications to detect changes in the host network configuration.
To be more clear you can find my proposed new header here:
https://gist.github.com/andreatosatto90/07d35be01ecfa50df083
Updated by Davide Pesavento almost 9 years ago
- Tracker changed from Task to Feature
Updated by Junxiao Shi almost 9 years ago
- Blocks Feature #3352: Set transport state UP/DOWN based on the state of the underlying network interface added
Updated by Davide Pesavento almost 9 years ago
- Subject changed from NetworkMonitor: emit signal when the state of a network interface changes to NetworkMonitor: emit fine-grained signals when the state of a network interface changes
- Description updated (diff)
- Start date deleted (
11/26/2015)
Updated by Davide Pesavento almost 9 years ago
- Status changed from In Progress to Code review
- % Done changed from 70 to 90
Updated by Davide Pesavento over 8 years ago
- Blocks Feature #3257: EthernetTransport: support runtime MTU changes added
Updated by Davide Pesavento over 8 years ago
- Blocks Feature #3521: Netdev-bound faces added
Updated by Junxiao Shi over 8 years ago
- Status changed from Code review to Feedback
- Assignee deleted (
Andrea Tosatto) - % Done changed from 90 to 50
There has been an incomplete submission in http://gerrit.named-data.net/2708, but Andrea is gone so someone else needs to finish it.
Updated by Junxiao Shi over 8 years ago
- Target version deleted (
v0.5)
20160719 call decides @Davide is responsible for finding a new assignee.
Updated by Jeff Burke about 8 years ago
- Priority changed from Normal to High
This is very important for demonstrating robustness.
Updated by Junxiao Shi about 8 years ago
- Assignee set to Weiwei Liu
- Priority changed from High to Normal
- Target version set to v0.6
Updated by Jeff Burke about 8 years ago
Why did the priority for this issue get lowered? It remains important to the application team for trying to make field deployments of NDN more resilient to connectivity changes. Needs to target v0.5 of dependent Feature #3521.
Updated by Junxiao Shi about 8 years ago
- Description updated (diff)
- Estimated time set to 6.00 h
Since the implementation is platform specific, we should finalize the Linux implementation within this issue. macOS platform implementation is split into #3817.
Updated by Junxiao Shi about 8 years ago
- Blocks Feature #3817: NetworkMonitor fine-grained signals for macOS added
Updated by Davide Pesavento about 8 years ago
- Status changed from Feedback to In Progress
Updated by Alex Afanasyev over 7 years ago
- Assignee set to Davide Pesavento
- Priority changed from High to Normal
Updated by Alex Afanasyev over 7 years ago
- Status changed from In Progress to Code review
Updated by Junxiao Shi over 7 years ago
- Blocks deleted (Feature #3521: Netdev-bound faces)
Updated by Junxiao Shi over 7 years ago
- Blocks Feature #4021: FaceSystem: use NetworkMonitor::listNetworkInterfaces() added
Updated by Junxiao Shi over 7 years ago
what would be the criteria to test this and the other patch? Just run integration test and observe that information is being properly updated?
NetworkMonitor itself is intrinsically not unit-testable. On the other hand, NetworkAddress and NetworkInterface could be unit tested.
This can be structured as a "manual test". A document should be placed at tests/integrated/network-monitor.txt
, which looks like:
- start
build/tests/integrated/network-monitor
program - execute
ip link add link eth0 name eth0-1
, NM should output "[eth0-1] onInterfaceAdded" - execute
ip addr 192.168.7.2/24 dev eth0-1
, NM should output "[eth0-1] onAddressAdded 192.168.7.2/24" - unplug the Ethernet cord on eth1 interface, NM should output "[eth1] onStateChanged no-carrier"
The steps may require the use of USB Ethernet adapters, WiFi interfaces, etc. Any step may be skipped if equipment is unavailable.
This allows anyone to test the program manually, given they have the right equipment. Compared to not providing this document, this removes the uncertainty on what would be the correct behavior given a certain action.
Updated by Junxiao Shi over 7 years ago
- Blocks Feature #4024: NetworkMonitor: stub implementation added
Updated by Junxiao Shi over 7 years ago
- Blocks Feature #4025: NetworkMonitor: empty impl on unsupported platform added
Updated by Junxiao Shi over 7 years ago
On Ubuntu 16.04 32-bit, http://gerrit.named-data.net/2708 patchset29 crashes if NetworkMonitor
is destructed before onEnumerationCompleted
is invoked.
// g++ -std=c++11 -o x x.cpp $(pkg-config --cflags --libs libndn-cxx)
#include <boost/asio.hpp>
#include <ndn-cxx/util/network-interface.hpp>
int
main()
{
boost::asio::io_service io;
std::unique_ptr<ndn::util::NetworkMonitor> nm(new ndn::util::NetworkMonitor(io));
nm->onInterfaceAdded.connect([&] (std::shared_ptr<ndn::util::NetworkInterface>) {
io.post([&] {
nm.reset();
});
});
io.run();
}
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<ndn::util::NetworkMonitor::Error> >'
what(): Netlink socket read failed (Bad file descriptor)
Thread 1 "x" received signal SIGABRT, Aborted.
0xb7fdac31 in __kernel_vsyscall ()
(gdb) bt full
#0 0xb7fdac31 in __kernel_vsyscall ()
No symbol table info available.
#1 0xb7b8cea9 in __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:54
resultvar = <optimized out>
resultvar = <optimized out>
pid = 27239
selftid = 27239
#2 0xb7b8e407 in __GI_abort () at abort.c:89
save_stage = 2
act = {__sigaction_handler = {sa_handler = 0xb7d3dfec,
sa_sigaction = 0xb7d3dfec}, sa_mask = {__val = {5, 3086997664,
3086895472, 3084112684, 5, 3086997664, 3085598748, 3086915490,
3086998104, 3081672512, 1, 5, 0, 3083939840, 3087003648,
3084198700, 3083943104, 3082577437, 3087003648, 3084198700, 48,
3084536027, 3086915307, 3082187192, 3083943416, 135031812,
3086915307, 3085598720, 3083943416, 135031812, 3221222088,
3086941968}}, sa_flags = 135031888,
sa_restorer = 0xb7b8e2b0 <__GI_abort>}
sigs = {__val = {32, 0 <repeats 31 times>}}
#3 0xb7da7d35 in __gnu_cxx::__verbose_terminate_handler() ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
No symbol table info available.
#4 0xb7da5833 in ?? () from /usr/lib/i386-linux-gnu/libstdc++.so.6
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#5 0xb7da58ad in std::terminate() ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
No symbol table info available.
#6 0xb7da5b70 in __cxa_throw () from /usr/lib/i386-linux-gnu/libstdc++.so.6
No symbol table info available.
#7 0x08070331 in boost::throw_exception<boost::exception_detail::error_info_injector<ndn::util::NetworkMonitor::Error> > (e=...)
at /usr/include/boost/throw_exception.hpp:69
No locals.
#8 0x08070412 in boost::exception_detail::throw_exception_<ndn::util::NetworkMonitor::Error> (x=...,
current_function=0x809e880 <ndn::util::NetworkMonitor::Impl::onReceiveRtnl(boost::system::error_code const&, unsigned int)::__PRETTY_FUNCTION__> "void ndn::util::NetworkMonitor::Impl::onReceiveRtnl(const boost::system::error_code&, size_t)", file=0x809e310 "../src/util/detail/network-monitor-impl-rtnl.cpp",
line=173) at /usr/include/boost/throw_exception.hpp:86
No locals.
#9 0x0806cb6f in ndn::util::NetworkMonitor::Impl::onReceiveRtnl (
this=0x80c1e78, error=..., nBytesReceived=0)
at ../src/util/detail/network-monitor-impl-rtnl.cpp:173
__func__ = "onReceiveRtnl"
__PRETTY_FUNCTION__ = "void ndn::util::NetworkMonitor::Impl::onReceiveRt---Type <return> to continue, or q <return> to quit---
nl(const boost::system::error_code&, size_t)"
nlh = <optimized out>
#10 0x08072577 in std::_Mem_fn_base<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int), true>::operator()<boost::system::error_code const&, unsigned int const&, void> (__object=<optimized out>,
this=0xbffff4e4) at /usr/include/c++/5/functional:600
No locals.
#11 std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>::__call<void, boost::system::error_code const&, unsigned int const&, 0u, 1u, 2u>(std::tuple<boost::system::error_code const&, unsigned int const&>&&, std::_Index_tuple<0u, 1u, 2u>) (
__args=<unknown type in /home/ubuntu/x, CU 0x2c49d, DIE 0x89fd0>,
this=0xbffff4e4) at /usr/include/c++/5/functional:1074
No locals.
#12 std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>::operator()<boost::system::error_code const&, unsigned int const&, void>(boost::system::error_code const&, unsigned int const&) (this=0xbffff4e4) at /usr/include/c++/5/functional:1133
No locals.
#13 boost::asio::detail::binder2<std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::---Type <return> to continue, or q <return> to quit---
NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>, boost::system::error_code, unsigned int>::operator()() (this=0xbffff4e4)
at /usr/include/boost/asio/detail/bind_handler.hpp:127
No locals.
#14 boost::asio::asio_handler_invoke<boost::asio::detail::binder2<std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>, boost::system::error_code, unsigned int> >(boost::asio::detail::binder2<std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>, boost::system::error_code, unsigned int>&, ...) (function=...)
at /usr/include/boost/asio/handler_invoke_hook.hpp:69
No locals.
#15 boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder2<std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>, boost::system::error_code, unsigned int>, std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)> >(boost::asio::detail::binder2<std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Pla---Type <return> to continue, or q <return> to quit---
ceholder<2>)>, boost::system::error_code, unsigned int>&, std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)>&) (context=..., function=...)
at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
No locals.
#16 boost::asio::detail::descriptor_read_op<boost::asio::mutable_buffers_1, std::_Bind<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> (ndn::util::NetworkMonitor::Impl*, std::_Placeholder<1>, std::_Placeholder<2>)> >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned int) (owner=0x80c1d70, base=0x80c6af8)
at /usr/include/boost/asio/detail/descriptor_read_op.hpp:104
o = <optimized out>
p = {h = 0xbffff4e4, v = 0x0, p = 0x0}
handler = {
handler_ = {<std::_Weak_result_type<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> >> = {<std::_Weak_result_type_impl<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)> >> = {<std::_Maybe_get_result_type<std::_Mem_fn<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int)>, void>> = {<No data fields>}, <No data fields>}, <No data fields>},
---Type <return> to continue, or q <return> to quit---
_M_f = {<std::_Mem_fn_base<void (ndn::util::NetworkMonitor::Impl::*)(boost::system::error_code const&, unsigned int), true>> = {<std::_Maybe_unary_or_binary_function<void, ndn::util::NetworkMonitor::Impl*, boost::system::error_code const&, unsigned int>> = {<No data fields>},
_M_pmf = (void (ndn::util::NetworkMonitor::Impl::*)(ndn::util::NetworkMonitor::Impl * const, const boost::system::error_code &,
unsigned int)) 0x806c36e <ndn::util::NetworkMonitor::Impl::onReceiveRtnl(boost::system::error_code const&, unsigned int)>}, <No data fields>},
_M_bound_args = std::tuple containing = {[1] = 0x80c1e78,
[2] = {<std::_Placeholder<1>> = {<No data fields>}, <No data fields>}, [3] = {<std::_Placeholder<2>> = {<No data fields>}, <No data fields>}}},
arg1_ = {m_val = 9, m_cat = 0xb7fcb064}, arg2_ = 0}
#17 0x08061018 in boost::asio::detail::task_io_service_operation::complete(boost::asio::detail::task_io_service&, boost::system::error_code const&, unsigned int) ()
No symbol table info available.
#18 0x08061eef in boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) ()
No symbol table info available.
#19 0x08061b1e in boost::asio::detail::task_io_service::run(boost::system::error_code&) ()
No symbol table info available.
---Type <return> to continue, or q <return> to quit---
#20 0x0806214d in boost::asio::io_service::run() ()
No symbol table info available.
#21 0x0805f2db in main ()
No symbol table info available.
Updated by Junxiao Shi over 7 years ago
- Blocks Feature #4027: FaceUri: canonize dev scheme added
Updated by Davide Pesavento over 7 years ago
Junxiao Shi wrote:
On Ubuntu 16.04 32-bit, http://gerrit.named-data.net/2708 patchset29 crashes if
NetworkMonitor
is destructed beforeonEnumerationCompleted
is invoked.
The crash is somewhat expected since an exception is being thrown from a destructor, which causes std::terminate
to be invoked. The real question is: why are you getting "bad file descriptor" at that point in the code?
Updated by Junxiao Shi over 7 years ago
- Blocks deleted (Feature #4027: FaceUri: canonize dev scheme)
Updated by Davide Pesavento over 7 years ago
We already encountered this problem in NFD (#1856).
When an Asio socket is destructed (or .close()
is called), pending handlers are invoked with no error (instead of boost::asio::error::operation_aborted
as documented). Therefore the handlers proceeds as if nothing bad happened and schedules another async read from the socket. However at that point the socket is closed, so the read results in a "bad file descriptor" error as above.
Patch set 30 solves this.
Updated by Davide Pesavento over 7 years ago
- Status changed from Code review to Closed
- % Done changed from 90 to 100
- Estimated time deleted (
6.00 h)
Finally.