Skip to content

Commit

Permalink
nl_bridge: handle port locked
Browse files Browse the repository at this point in the history
Update learning mode for bridge ports based on lock state.

Signed-off-by: Jonas Gorski <jonas.gorski@bisdn.de>
  • Loading branch information
KanjiMonster committed Jan 17, 2025
1 parent 9be1bd5 commit b8713f7
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
50 changes: 47 additions & 3 deletions src/netlink/nl_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,16 @@ void nl_bridge::add_interface(rtnl_link *link) {
return;
}

auto locked = (rtnl_link_bridge_get_flags(link) & RTNL_BRIDGE_LOCKED) != 0;
LOG(INFO) << __FUNCTION__ << ": link " << rtnl_link_get_name(link) << " is "
<< (locked ? "LOCKED" : "UNLOCKED");
auto state = rtnl_link_bridge_get_port_state(link);
auto port_id = nl->get_port_id(link);
if (port_id > 0)

if (port_id > 0) {
set_port_stp_state(port_id, state);
set_port_locked(port_id, locked);
}

// configure bonds and physical ports (non members of bond)
update_vlans(nullptr, link);
Expand Down Expand Up @@ -225,17 +231,30 @@ void nl_bridge::update_interface(rtnl_link *old_link, rtnl_link *new_link) {
auto new_state = rtnl_link_bridge_get_port_state(new_link);
std::string state;

auto port_id = nl->get_port_id(new_link);
if (old_state != new_state) {
LOG(INFO) << __FUNCTION__ << " STP state changed, old=" << old_state
<< " new=" << new_state;

auto port_id = nl->get_port_id(new_link);
if (port_id > 0)
set_port_stp_state(port_id, new_state);
return;
}

update_vlans(old_link, new_link);

auto old_locked =
(rtnl_link_bridge_get_flags(old_link) & RTNL_BRIDGE_LOCKED) != 0;
auto new_locked =
(rtnl_link_bridge_get_flags(new_link) & RTNL_BRIDGE_LOCKED) != 0;

if (old_locked ^ new_locked) {
LOG(INFO) << __FUNCTION__ << ": link " << rtnl_link_get_name(new_link)
<< " is now " << (new_locked ? "LOCKED" : "UNLOCKED");

if (port_id > 0)
set_port_locked(port_id, new_locked);
}
}

void nl_bridge::delete_interface(rtnl_link *link) {
Expand All @@ -259,8 +278,10 @@ void nl_bridge::delete_interface(rtnl_link *link) {

auto port_id = nl->get_port_id(link);
// interface default is to STP state forward by default
if (port_id > 0)
if (port_id > 0) {
set_port_stp_state(port_id, BR_STATE_FORWARDING);
set_port_locked(port_id, false);
}
}

void nl_bridge::update_vlans(rtnl_link *old_link, rtnl_link *new_link) {
Expand Down Expand Up @@ -1178,4 +1199,27 @@ nl_bridge::get_port_vlan_stp_states(rtnl_link *link) {
return bridge_stp_states.get_min_states(port_id);
}

void nl_bridge::set_port_locked(uint32_t port_id, bool locked) {
std::set<uint32_t> ports;

if (nbi::get_port_type(port_id) == nbi::port_type_lag)
ports = get_bond_members_by_port_id(port_id);
else
ports.insert(port_id);

for (auto port : ports) {
if (locked) {
/* learn pending, but don't forward */
sw->port_set_learn(port, switch_interface::SAI_SRC_LEARN_NOTIFICATION);
/* kernel does not allow roaming to locked ports, so just drop it */
sw->port_set_move_learn(port, switch_interface::SAI_SRC_LEARN_DROP);
} else {
/* everything goes */
sw->port_set_learn(port, switch_interface::SAI_SRC_LEARN_HW_NOTIFICATION);
sw->port_set_move_learn(port,
switch_interface::SAI_SRC_LEARN_HW_NOTIFICATION);
}
}
}

} /* namespace basebox */
2 changes: 2 additions & 0 deletions src/netlink/nl_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ class nl_bridge {
int update_access_ports(rtnl_link *vxlan_link, rtnl_link *br_link,
const uint32_t tunnel_id, bool add);

void set_port_locked(uint32_t port_id, bool locked);

private:
struct bridge_stp_states bridge_stp_states;

Expand Down

0 comments on commit b8713f7

Please sign in to comment.