/** * Delete a neighbour * @arg handle netlink handle * @arg neigh neighbour to delete * * Builds a netlink message by calling rtnl_neigh_build_delete_request(), * sends the request to the kernel and waits for the next ACK to be * received and thus blocks until the request has been fullfilled. * * @return 0 on sucess or a negative error if an error occured. */ int rtnl_neigh_delete(struct nl_handle *handle, struct rtnl_neigh *neigh) { int err; struct nl_msg *m = rtnl_neigh_build_delete_request(neigh); if ((err = nl_send_auto_complete(handle, nl_msg_get(m))) < 0) return err; nl_msg_free(m); return nl_wait_for_ack(handle); }
int nl_bridge::fdb_timeout(rtnl_link *br_link, uint16_t vid, const rofl::caddress_ll &mac) { int rv = 0; std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n(rtnl_neigh_alloc(), rtnl_neigh_put); std::unique_ptr<nl_addr, decltype(&nl_addr_put)> h_src( nl_addr_build(AF_LLC, mac.somem(), mac.memlen()), nl_addr_put); rtnl_neigh_set_ifindex(n.get(), rtnl_link_get_ifindex(br_link)); rtnl_neigh_set_master(n.get(), rtnl_link_get_master(br_link)); rtnl_neigh_set_family(n.get(), AF_BRIDGE); rtnl_neigh_set_vlan(n.get(), vid); rtnl_neigh_set_lladdr(n.get(), h_src.get()); rtnl_neigh_set_flags(n.get(), NTF_MASTER | NTF_EXT_LEARNED); rtnl_neigh_set_state(n.get(), NUD_REACHABLE); // find entry in local l2_cache std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n_lookup( NEIGH_CAST(nl_cache_search(l2_cache.get(), OBJ_CAST(n.get()))), rtnl_neigh_put); if (n_lookup) { // * remove l2 entry from kernel nl_msg *msg = nullptr; rtnl_neigh_build_delete_request(n.get(), NLM_F_REQUEST, &msg); assert(msg); // send the message and create new fdb entry if (nl->send_nl_msg(msg) < 0) { LOG(ERROR) << __FUNCTION__ << ": failed to send netlink message"; return -EINVAL; } // XXX TODO maybe delete after NL event and not yet here nl_cache_remove(OBJ_CAST(n_lookup.get())); } return rv; }