Skip to content

Commit

Permalink
don't discard netlink messages for previously seen addresses
Browse files Browse the repository at this point in the history
Addresses can come and go. Supressing notifications for previously seen addresses
can cause the client to miss when the address is re-added. New address
notifications also don't necessarily include an IFA_LOCAL attribute so don't
filter on that either. Note that notifications don't cause all listen sockets
to be closed and re-opened. Despite its name reopen_listen_sockets only
closes/opens sockets as necessary to synchronize with the list of addresses
enumerated from the OS.
  • Loading branch information
ssiloti authored and arvidn committed Sep 30, 2024
1 parent 790b662 commit 685a104
Showing 1 changed file with 3 additions and 35 deletions.
38 changes: 3 additions & 35 deletions src/ip_notifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,6 @@ struct ip_change_notifier_impl final : ip_change_notifier
netlink::socket m_socket;
std::array<char, 4096> m_buf;

struct local_address
{
int family;
std::array<char, 16> data;
};
// maps if_index to the most recently advertised local address
// this is used to filter duplicate updates
std::unordered_map<std::uint32_t, local_address> m_state;

void on_notify(int len, std::function<void(error_code const& ec)> cb)
{
bool pertinent = false;
Expand All @@ -184,33 +175,10 @@ struct ip_change_notifier_impl final : ip_change_notifier
nlmsg_ok (nh, len);
nh = nlmsg_next(nh, len))
{
if (nh->nlmsg_type != RTM_NEWADDR)
if (nh->nlmsg_type != RTM_NEWADDR &&
nh->nlmsg_type != RTM_DELADDR)
continue;

auto const* addr_msg = static_cast<ifaddrmsg const*>(nlmsg_data(nh));
std::uint32_t const index = addr_msg->ifa_index;
int const family = addr_msg->ifa_family;
std::size_t attr_len = ifa_payload(nh);
auto const* rta_ptr = ifa_rta(addr_msg);

for (; rta_ok(rta_ptr, attr_len); rta_ptr = rta_next(rta_ptr, attr_len))
{
auto* const ptr = rta_data(rta_ptr);
if (rta_ptr->rta_type != IFA_LOCAL)
continue;

auto& existing = m_state[index];
std::size_t const address_len = family == AF_INET ? 4 : 16;
if (existing.family == family
&& std::memcmp(&existing.data, ptr, address_len) == 0)
{
break;
}

existing.family = family;
std::memcpy(existing.data.data(), ptr, address_len);
pertinent = true;
}
pertinent = true;
}

if (!pertinent)
Expand Down

0 comments on commit 685a104

Please sign in to comment.