Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/jogo_fdb_flush' into baseboxdnext
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensfig committed Aug 14, 2024
2 parents 6466d00 + cb05923 commit b501b35
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 6 deletions.
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ sources = files('''
src/netlink/nl_hashing.h
src/netlink/nl_interface.cc
src/netlink/nl_interface.h
src/netlink/nl_fdb_flush.h
src/netlink/nl_l3.cc
src/netlink/nl_l3.h
src/netlink/nl_l3_interfaces.h
Expand Down
29 changes: 23 additions & 6 deletions src/netlink/nl_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "cnetlink.h"
#include "netlink-utils.h"
#include "nl_bridge.h"
#include "nl_fdb_flush.h"
#include "nl_output.h"
#include "nl_vlan.h"
#include "nl_vxlan.h"
Expand Down Expand Up @@ -485,6 +486,15 @@ void nl_bridge::update_vlans(rtnl_link *old_link, rtnl_link *new_link) {

// the PVID is already being handled outside of the loop
vlan->remove_bridge_vlan(_link, vid, false, !egress_untagged);

// remove all fdb entries by us
nl_fdb_flush ff;

auto ret = ff.flush_fdb(rtnl_link_get_ifindex(_link), vid,
NTF_MASTER | NTF_EXT_LEARNED);
if (ret < 0)
LOG(WARNING) << __FUNCTION__ << ": failed to flush vid=" << vid
<< " on port " << _link;
}
}
}
Expand Down Expand Up @@ -781,13 +791,20 @@ void nl_bridge::remove_neigh_from_fdb(rtnl_neigh *neigh) {
return;
}

// lookup l2_cache as well
std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n_lookup(
NEIGH_CAST(nl_cache_search(l2_cache.get(), OBJ_CAST(neigh))),
rtnl_neigh_put);
if ((rtnl_neigh_get_flags(neigh) & NTF_EXT_LEARNED) == NTF_EXT_LEARNED) {
// lookup l2_cache as well
std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n_lookup(
NEIGH_CAST(nl_cache_search(l2_cache.get(), OBJ_CAST(neigh))),
rtnl_neigh_put);

if (n_lookup) {
nl_cache_remove(OBJ_CAST(n_lookup.get()));
if (n_lookup) {
nl_cache_remove(OBJ_CAST(n_lookup.get()));
} else {
// if we flushed the entry, we already removed it from cache and flows, so
// no need to do anything here
VLOG(2) << __FUNCTION__ << ": neigh not found in cache" << neigh;
return;
}
}

const uint32_t port = nl->get_port_id(rtnl_neigh_get_ifindex(neigh));
Expand Down
79 changes: 79 additions & 0 deletions src/netlink/nl_fdb_flush.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#pragma once

#include <cassert>
#include <chrono>
#include <future>
#include <iostream>
#include <thread>

#include <glog/logging.h>

#include <netlink/attr.h>
#include <linux/rtnetlink.h>

#include "nl_output.h"

namespace basebox {

class nl_fdb_flush final {
struct nl_sock *sock;

public:
nl_fdb_flush() {
sock = nl_socket_alloc();
int err;
if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0)
LOG(FATAL) << __FUNCTION__ << ": Unable to connect netlink socket: %s"
<< nl_geterror(err);
}

~nl_fdb_flush() { nl_socket_free(sock); }

/**
* flush fdb
*/
int flush_fdb(int ifindex, uint16_t vlan, uint8_t flags) {
struct nl_msg *m;
struct ndmsg ndm;
int err;

memset(&ndm, 0, sizeof(ndm));
ndm.ndm_family = PF_BRIDGE;
ndm.ndm_ifindex = ifindex;
ndm.ndm_flags = flags;

m = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_REQUEST | NLM_F_BULK);
if (!m)
LOG(FATAL) << __FUNCTION__ << ": out of memory";

if (nlmsg_append(m, &ndm, sizeof(ndm), NLMSG_ALIGNTO) < 0)
LOG(FATAL) << __FUNCTION__ << ": out of memory";

if (vlan > 0) {
if (nla_put_u16(m, NDA_VLAN, vlan) < 0)
LOG(FATAL) << __FUNCTION__ << ": out of memory";
}

if (flags > 0) {
if (nla_put_u8(m, NDA_NDM_FLAGS_MASK, flags) < 0)
LOG(FATAL) << __FUNCTION__ << ": out of memory";
}

err = nl_send_auto_complete(sock, m);
nlmsg_free(m);
if (err < 0)
LOG(FATAL) << __FUNCTION__ << ": " << nl_geterror(err);

if ((err = nl_recvmsgs_default(sock)) < 0) {
LOG(FATAL) << __FUNCTION__ << ": " << nl_geterror(err);
}

return 0;
}
};

} // namespace basebox

0 comments on commit b501b35

Please sign in to comment.