@@ -247,7 +247,10 @@ struct switchdev_notifier_fdb_info {
const unsigned char *addr;
u16 vid;
u8 added_by_user:1,
+ sticky:1,
is_local:1,
+ locked:1,
+ blackhole:1,
offloaded:1;
};
@@ -166,7 +166,10 @@ static int br_switchdev_event(struct notifier_block *unused,
case SWITCHDEV_FDB_ADD_TO_BRIDGE:
fdb_info = ptr;
err = br_fdb_external_learn_add(br, p, fdb_info->addr,
- fdb_info->vid, false);
+ fdb_info->vid, false,
+ fdb_info->locked,
+ fdb_info->blackhole,
+ fdb_info->sticky);
if (err) {
err = notifier_from_errno(err);
break;
@@ -1147,7 +1147,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
"FDB entry towards bridge must be permanent");
return -EINVAL;
}
- err = br_fdb_external_learn_add(br, p, addr, vid, true);
+ err = br_fdb_external_learn_add(br, p, addr, vid, true, false, false, false);
} else {
spin_lock_bh(&br->hash_lock);
err = fdb_add_entry(br, p, addr, ndm, nlh_flags, vid, nfea_tb);
@@ -1383,7 +1383,8 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid,
- bool swdev_notify)
+ bool swdev_notify, bool locked,
+ bool blackhole, bool sticky)
{
struct net_bridge_fdb_entry *fdb;
bool modified = false;
@@ -1403,6 +1404,15 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
if (!p)
flags |= BIT(BR_FDB_LOCAL);
+ if (locked)
+ flags |= BIT(BR_FDB_ENTRY_LOCKED);
+
+ if (blackhole)
+ flags |= BIT(BR_FDB_BLACKHOLE);
+
+ if (sticky)
+ flags |= BIT(BR_FDB_STICKY);
+
fdb = fdb_create(br, p, addr, vid, flags);
if (!fdb) {
err = -ENOMEM;
@@ -812,7 +812,8 @@ int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid,
- bool swdev_notify);
+ bool swdev_notify, bool locked,
+ bool blackhole, bool sticky);
int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid,
bool swdev_notify);
@@ -71,8 +71,8 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
}
/* Flags that can be offloaded to hardware */
-#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
- BR_MCAST_FLOOD | BR_BCAST_FLOOD | BR_PORT_LOCKED | \
+#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD | \
+ BR_PORT_LOCKED | BR_PORT_MAB | \
BR_HAIRPIN_MODE | BR_ISOLATED | BR_MULTICAST_TO_UNICAST)
int br_switchdev_set_port_flag(struct net_bridge_port *p,
@@ -136,6 +136,7 @@ static void br_switchdev_fdb_populate(struct net_bridge *br,
item->added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
item->offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags);
item->is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
+ item->locked = test_bit(BR_FDB_ENTRY_LOCKED, &fdb->flags);
item->info.dev = (!p || item->is_local) ? br->dev : p->dev;
item->info.ctx = ctx;
}
@@ -65,6 +65,7 @@ struct dsa_notifier_fdb_info {
const struct dsa_port *dp;
const unsigned char *addr;
u16 vid;
+ bool is_locked;
struct dsa_db db;
};
@@ -131,6 +132,7 @@ struct dsa_switchdev_event_work {
unsigned char addr[ETH_ALEN];
u16 vid;
bool host_addr;
+ bool is_locked;
};
enum dsa_standalone_event {
@@ -232,7 +234,7 @@ int dsa_port_vlan_msti(struct dsa_port *dp,
const struct switchdev_vlan_msti *msti);
int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu);
int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
- u16 vid);
+ u16 vid, bool is_locked);
int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
u16 vid);
int dsa_port_standalone_host_fdb_add(struct dsa_port *dp,
@@ -303,7 +303,7 @@ static int dsa_port_inherit_brport_flags(struct dsa_port *dp,
struct netlink_ext_ack *extack)
{
const unsigned long mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
- BR_BCAST_FLOOD | BR_PORT_LOCKED;
+ BR_BCAST_FLOOD | BR_PORT_LOCKED | BR_PORT_MAB;
struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
int flag, err;
@@ -327,7 +327,7 @@ static void dsa_port_clear_brport_flags(struct dsa_port *dp)
{
const unsigned long val = BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
const unsigned long mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
- BR_BCAST_FLOOD | BR_PORT_LOCKED;
+ BR_BCAST_FLOOD | BR_PORT_LOCKED | BR_PORT_MAB;
int flag, err;
for_each_set_bit(flag, &mask, 32) {
@@ -954,12 +954,13 @@ int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu)
}
int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
- u16 vid)
+ u16 vid, bool is_locked)
{
struct dsa_notifier_fdb_info info = {
.dp = dp,
.addr = addr,
.vid = vid,
+ .is_locked = is_locked,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
@@ -2908,6 +2908,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
container_of(work, struct dsa_switchdev_event_work, work);
const unsigned char *addr = switchdev_work->addr;
struct net_device *dev = switchdev_work->dev;
+ bool is_locked = switchdev_work->is_locked;
u16 vid = switchdev_work->vid;
struct dsa_switch *ds;
struct dsa_port *dp;
@@ -2923,7 +2924,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
else if (dp->lag)
err = dsa_port_lag_fdb_add(dp, addr, vid);
else
- err = dsa_port_fdb_add(dp, addr, vid);
+ err = dsa_port_fdb_add(dp, addr, vid, is_locked);
if (err) {
dev_err(ds->dev,
"port %d failed to add %pM vid %d to fdb: %d\n",
@@ -3031,6 +3032,7 @@ static int dsa_slave_fdb_event(struct net_device *dev,
ether_addr_copy(switchdev_work->addr, fdb_info->addr);
switchdev_work->vid = fdb_info->vid;
switchdev_work->host_addr = host_addr;
+ switchdev_work->is_locked = fdb_info->locked;
dsa_schedule_work(&switchdev_work->work);
@@ -234,7 +234,7 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp,
}
static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
- u16 vid, struct dsa_db db)
+ u16 vid, bool is_locked, struct dsa_db db)
{
struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a;
@@ -399,7 +399,7 @@ static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->dp)) {
err = dsa_port_do_fdb_add(dp, info->addr, info->vid,
- info->db);
+ false, info->db);
if (err)
break;
}
@@ -438,7 +438,7 @@ static int dsa_switch_fdb_add(struct dsa_switch *ds,
if (!ds->ops->port_fdb_add)
return -EOPNOTSUPP;
- return dsa_port_do_fdb_add(dp, info->addr, info->vid, info->db);
+ return dsa_port_do_fdb_add(dp, info->addr, info->vid, info->is_locked, info->db);
}
static int dsa_switch_fdb_del(struct dsa_switch *ds,
Used for MacAuth/MAB feature in the offloaded case. Send the fdb locked flag down through the switchdev and DSA layers. Also add support for drivers to set additional flags on bridge FDB entries including the new 'blackhole' flag. And add support for offloading of the MAB/MacAuth feature flag. Signed-off-by: Hans Schultz <netdev@kapio-technology.com> --- include/net/switchdev.h | 3 +++ net/bridge/br.c | 5 ++++- net/bridge/br_fdb.c | 14 ++++++++++++-- net/bridge/br_private.h | 3 ++- net/bridge/br_switchdev.c | 5 +++-- net/dsa/dsa_priv.h | 4 +++- net/dsa/port.c | 7 ++++--- net/dsa/slave.c | 4 +++- net/dsa/switch.c | 6 +++--- 9 files changed, 37 insertions(+), 14 deletions(-)