Skip to content

Commit

Permalink
cnetlink::get_neighbor() check pending notification for deleted neighs
Browse files Browse the repository at this point in the history
When a route and its nexthop (neigh) get removed at the same time, we
may process the route removal before the neigh removal.

On route removal we try to unregister for nexthop notifications, and
remove any pending l3 interfaces.

Since cnetlink::get_neighbour() only asks the cache, it only returns
live neighs, but since the neigh was already removed from the cache,
it wont find any.

At the same time, since we did not process the neigh removal yet, we are
still registered for nh unreachable notifications, but since from the
perspective of the nl_l3::del_l3_route(), the nexthop is already
unreachable, so we fail to remove the unreachable notification.

Fix this by also going through the pending neigh deletions to find the
reference in case there is a neigh delete pending.

Fixes: dfe4485 ("add netlink functions")
Signed-off-by: Jonas Gorski <[email protected]>
  • Loading branch information
KanjiMonster committed May 29, 2024
1 parent 38b1eef commit b85be60
Showing 1 changed file with 32 additions and 1 deletion.
33 changes: 32 additions & 1 deletion src/netlink/cnetlink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,39 @@ struct rtnl_neigh *cnetlink::get_neighbour(int ifindex,
struct nl_addr *a) const {
assert(ifindex);
assert(a);

auto neigh = rtnl_neigh_get(caches[NL_NEIGH_CACHE], ifindex, a);

// check the garbage
if (neigh == nullptr) {
for (auto &obj : nl_objs) {
rtnl_neigh *n;

if (obj.get_action() != NL_ACT_DEL)
continue;

if (std::string("route/neigh")
.compare(nl_object_get_type(obj.get_old_obj())) != 0)
continue;

n = NEIGH_CAST(obj.get_old_obj());

if (rtnl_neigh_get_ifindex(n) != ifindex)
continue;

if (rtnl_neigh_get_family(n) != nl_addr_get_family(a))
continue;

if (nl_addr_cmp(rtnl_neigh_get_dst(n), a) == 0) {
nl_object_get(OBJ_CAST(n));
neigh = n;
break;
}
}
}

// XXX TODO return unique_ptr
return rtnl_neigh_get(caches[NL_NEIGH_CACHE], ifindex, a);
return neigh;
}

bool cnetlink::is_bridge_interface(int ifindex) const {
Expand Down

0 comments on commit b85be60

Please sign in to comment.