Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/netlink/cnetlink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,11 @@ void cnetlink::handle_read_event(rofl::cthread &thread, int fd) {
if (fd == nl_cache_mngr_get_fd(mngr)) {
int rv = nl_cache_mngr_data_ready(mngr);
VLOG(3) << __FUNCTION__ << ": #processed=" << rv;
if (sync_route_cache) {
sync_route_cache = false;
nl_cache_resync_v2(sock_tx, caches[NL_ROUTE_CACHE],
(change_func_v2_t)&nl_cb_v2, this);
}
// notify update
if (state != NL_STATE_STOPPED) {
this->thread.wakeup(this);
Expand Down Expand Up @@ -1025,6 +1030,27 @@ void cnetlink::nl_cb_v2(struct nl_cache *cache, struct nl_object *old_obj,

// only enqueue nl msgs if not in stopped state
if (nl->state != NL_STATE_STOPPED) {
// linkdown events will silently delete routes with nexthops from that link,
// so we need to explicitly resync routes to catch those removed routes
if ((action == NL_ACT_CHANGE &&
nl_object_get_msgtype(old_obj) == RTM_NEWLINK) ||
(action == NL_ACT_DEL &&
nl_object_get_msgtype(old_obj) == RTM_DELLINK)) {
bool old_link, new_link = false;

old_link = (rtnl_link_get_flags(LINK_CAST(old_obj)) &
(IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING);

if (new_obj != nullptr)
new_link = (rtnl_link_get_flags(LINK_CAST(new_obj)) &
(IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING);

// link state event => nh and routes targeting them may have been altered
// silently by kernel, so sync the route cache
if (old_link != new_link)
nl->sync_route_cache = true;
}

// If libnl updated the object instead of replacing it, old_obj will be a
// clone of the old object, and new_obj is the updated old object. Since
// later notifications may update the new_obj further, clone
Expand Down
1 change: 1 addition & 0 deletions src/netlink/cnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class cnetlink final : public rofl::cthread_env {

int nl_proc_max;
enum nl_state state;
bool sync_route_cache;
std::deque<nl_obj> nl_objs;

std::shared_ptr<port_manager> port_man;
Expand Down
11 changes: 8 additions & 3 deletions src/netlink/nl_l3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1970,9 +1970,14 @@ int nl_l3::add_l3_unicast_route(rtnl_route *r, bool update_route) {
int nl_l3::update_l3_unicast_route(rtnl_route *r_old, rtnl_route *r_new) {
int rv = 0;

// currently we will only handle next hop changes
add_l3_unicast_route(r_new, true);
del_l3_unicast_route(r_old, true);
if (rtnl_route_guess_scope(r_old) != RT_SCOPE_LINK &&
rtnl_route_guess_scope(r_new) != RT_SCOPE_LINK) {
// currently we will only handle next hop changes
add_l3_unicast_route(r_new, true);
del_l3_unicast_route(r_old, true);
} else {
VLOG(2) << __FUNCTION__ << ": update of link scope routes not supported";
}

return rv;
}
Expand Down