Skip to content

Commit 21446c0

Browse files
pmachatakuba-moo
authored andcommitted
net: bridge: Introduce UAPI for BR_BOOLOPT_FDB_LOCAL_VLAN_0
The previous patches introduced a new option, BR_BOOLOPT_FDB_LOCAL_VLAN_0. When enabled, it has local FDB entries installed only on VLAN 0, instead of duplicating them across all VLANs. In this patch, add the corresponding UAPI toggle, and the code for turning the feature on and off. Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: Petr Machata <[email protected]> Acked-by: Nikolay Aleksandrov <[email protected]> Link: https://patch.msgid.link/ea99bfb10f687fa58091e6e1c2f8acc33f47ca45.1757004393.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent a29aba6 commit 21446c0

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

include/uapi/linux/if_bridge.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,8 @@ struct br_mcast_stats {
823823
/* bridge boolean options
824824
* BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets
825825
* BR_BOOLOPT_MCAST_VLAN_SNOOPING - control vlan multicast snooping
826+
* BR_BOOLOPT_FDB_LOCAL_VLAN_0 - local FDB entries installed by the bridge
827+
* driver itself should only be added on VLAN 0
826828
*
827829
* IMPORTANT: if adding a new option do not forget to handle
828830
* it in br_boolopt_toggle/get and bridge sysfs
@@ -832,6 +834,7 @@ enum br_boolopt_id {
832834
BR_BOOLOPT_MCAST_VLAN_SNOOPING,
833835
BR_BOOLOPT_MST_ENABLE,
834836
BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION,
837+
BR_BOOLOPT_FDB_LOCAL_VLAN_0,
835838
BR_BOOLOPT_MAX
836839
};
837840

net/bridge/br.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,23 @@ static struct notifier_block br_switchdev_blocking_notifier = {
259259
.notifier_call = br_switchdev_blocking_event,
260260
};
261261

262+
static int
263+
br_toggle_fdb_local_vlan_0(struct net_bridge *br, bool on,
264+
struct netlink_ext_ack *extack)
265+
{
266+
int err;
267+
268+
if (br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0) == on)
269+
return 0;
270+
271+
err = br_fdb_toggle_local_vlan_0(br, on, extack);
272+
if (err)
273+
return err;
274+
275+
br_opt_toggle(br, BROPT_FDB_LOCAL_VLAN_0, on);
276+
return 0;
277+
}
278+
262279
/* br_boolopt_toggle - change user-controlled boolean option
263280
*
264281
* @br: bridge device
@@ -287,6 +304,9 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on,
287304
case BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION:
288305
br_opt_toggle(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION, on);
289306
break;
307+
case BR_BOOLOPT_FDB_LOCAL_VLAN_0:
308+
err = br_toggle_fdb_local_vlan_0(br, on, extack);
309+
break;
290310
default:
291311
/* shouldn't be called with unsupported options */
292312
WARN_ON(1);
@@ -307,6 +327,8 @@ int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
307327
return br_opt_get(br, BROPT_MST_ENABLED);
308328
case BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION:
309329
return br_opt_get(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION);
330+
case BR_BOOLOPT_FDB_LOCAL_VLAN_0:
331+
return br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0);
310332
default:
311333
/* shouldn't be called with unsupported options */
312334
WARN_ON(1);

net/bridge/br_fdb.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,102 @@ void br_fdb_cleanup(struct work_struct *work)
582582
mod_delayed_work(system_long_wq, &br->gc_work, work_delay);
583583
}
584584

585+
static void br_fdb_delete_locals_per_vlan_port(struct net_bridge *br,
586+
struct net_bridge_port *p)
587+
{
588+
struct net_bridge_vlan_group *vg;
589+
struct net_bridge_vlan *v;
590+
struct net_device *dev;
591+
592+
if (p) {
593+
vg = nbp_vlan_group(p);
594+
dev = p->dev;
595+
} else {
596+
vg = br_vlan_group(br);
597+
dev = br->dev;
598+
}
599+
600+
list_for_each_entry(v, &vg->vlan_list, vlist)
601+
br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid);
602+
}
603+
604+
static void br_fdb_delete_locals_per_vlan(struct net_bridge *br)
605+
{
606+
struct net_bridge_port *p;
607+
608+
ASSERT_RTNL();
609+
610+
list_for_each_entry(p, &br->port_list, list)
611+
br_fdb_delete_locals_per_vlan_port(br, p);
612+
613+
br_fdb_delete_locals_per_vlan_port(br, NULL);
614+
}
615+
616+
static int br_fdb_insert_locals_per_vlan_port(struct net_bridge *br,
617+
struct net_bridge_port *p,
618+
struct netlink_ext_ack *extack)
619+
{
620+
struct net_bridge_vlan_group *vg;
621+
struct net_bridge_vlan *v;
622+
struct net_device *dev;
623+
int err;
624+
625+
if (p) {
626+
vg = nbp_vlan_group(p);
627+
dev = p->dev;
628+
} else {
629+
vg = br_vlan_group(br);
630+
dev = br->dev;
631+
}
632+
633+
list_for_each_entry(v, &vg->vlan_list, vlist) {
634+
if (!br_vlan_should_use(v))
635+
continue;
636+
637+
err = br_fdb_add_local(br, p, dev->dev_addr, v->vid);
638+
if (err)
639+
return err;
640+
}
641+
642+
return 0;
643+
}
644+
645+
static int br_fdb_insert_locals_per_vlan(struct net_bridge *br,
646+
struct netlink_ext_ack *extack)
647+
{
648+
struct net_bridge_port *p;
649+
int err;
650+
651+
ASSERT_RTNL();
652+
653+
list_for_each_entry(p, &br->port_list, list) {
654+
err = br_fdb_insert_locals_per_vlan_port(br, p, extack);
655+
if (err)
656+
goto rollback;
657+
}
658+
659+
err = br_fdb_insert_locals_per_vlan_port(br, NULL, extack);
660+
if (err)
661+
goto rollback;
662+
663+
return 0;
664+
665+
rollback:
666+
NL_SET_ERR_MSG_MOD(extack, "fdb_local_vlan_0 toggle: FDB entry insertion failed");
667+
br_fdb_delete_locals_per_vlan(br);
668+
return err;
669+
}
670+
671+
int br_fdb_toggle_local_vlan_0(struct net_bridge *br, bool on,
672+
struct netlink_ext_ack *extack)
673+
{
674+
if (!on)
675+
return br_fdb_insert_locals_per_vlan(br, extack);
676+
677+
br_fdb_delete_locals_per_vlan(br);
678+
return 0;
679+
}
680+
585681
static bool __fdb_flush_matches(const struct net_bridge *br,
586682
const struct net_bridge_fdb_entry *f,
587683
const struct net_bridge_fdb_flush_desc *desc)

net/bridge/br_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,8 @@ void br_fdb_find_delete_local(struct net_bridge *br,
844844
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr);
845845
void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr);
846846
void br_fdb_cleanup(struct work_struct *work);
847+
int br_fdb_toggle_local_vlan_0(struct net_bridge *br, bool on,
848+
struct netlink_ext_ack *extack);
847849
void br_fdb_delete_by_port(struct net_bridge *br,
848850
const struct net_bridge_port *p, u16 vid, int do_all);
849851
struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,

0 commit comments

Comments
 (0)