Merge branch 'BR_FDB_LOCAL'
Vladimir Oltean says: ==================== Pass the BR_FDB_LOCAL information to switchdev drivers Bridge FDB entries with the is_local flag are entries which are terminated locally and not forwarded. Switchdev drivers might want to be notified of these addresses so they can trap them. If they don't program these entries to hardware, there is no guarantee that they will do the right thing with these entries, and they won't be, let's say, flooded. Ideally none of the switchdev drivers should ignore these entries, but having access to the is_local bit is the bare minimum change that should be done in the bridge layer, before this is even possible. These 2 changes are extracted from the larger "RX filtering in DSA" series: https://patchwork.kernel.org/project/netdevbpf/patch/20210224114350.2791260-8-olteanv@gmail.com/ https://patchwork.kernel.org/project/netdevbpf/patch/20210224114350.2791260-9-olteanv@gmail.com/ and submitted separately, because they touch all switchdev drivers, while the rest is mostly specific to DSA. This change is not a functional one, in the sense that everybody still ignores the local FDB entries, but this will be changed by further patches at least for DSA. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
2576e5d31f
|
@ -2098,7 +2098,7 @@ static void dpaa2_switch_event_work(struct work_struct *work)
|
||||||
|
|
||||||
switch (switchdev_work->event) {
|
switch (switchdev_work->event) {
|
||||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
break;
|
break;
|
||||||
if (is_unicast_ether_addr(fdb_info->addr))
|
if (is_unicast_ether_addr(fdb_info->addr))
|
||||||
err = dpaa2_switch_port_fdb_add_uc(netdev_priv(dev),
|
err = dpaa2_switch_port_fdb_add_uc(netdev_priv(dev),
|
||||||
|
@ -2113,7 +2113,7 @@ static void dpaa2_switch_event_work(struct work_struct *work)
|
||||||
&fdb_info->info, NULL);
|
&fdb_info->info, NULL);
|
||||||
break;
|
break;
|
||||||
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
break;
|
break;
|
||||||
if (is_unicast_ether_addr(fdb_info->addr))
|
if (is_unicast_ether_addr(fdb_info->addr))
|
||||||
dpaa2_switch_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr);
|
dpaa2_switch_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr);
|
||||||
|
|
|
@ -798,7 +798,7 @@ static void prestera_fdb_event_work(struct work_struct *work)
|
||||||
switch (swdev_work->event) {
|
switch (swdev_work->event) {
|
||||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||||
fdb_info = &swdev_work->fdb_info;
|
fdb_info = &swdev_work->fdb_info;
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = prestera_port_fdb_set(port, fdb_info, true);
|
err = prestera_port_fdb_set(port, fdb_info, true);
|
||||||
|
|
|
@ -2916,7 +2916,8 @@ mlxsw_sp_switchdev_bridge_nve_fdb_event(struct mlxsw_sp_switchdev_event_work *
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (switchdev_work->event == SWITCHDEV_FDB_ADD_TO_DEVICE &&
|
if (switchdev_work->event == SWITCHDEV_FDB_ADD_TO_DEVICE &&
|
||||||
!switchdev_work->fdb_info.added_by_user)
|
(!switchdev_work->fdb_info.added_by_user ||
|
||||||
|
switchdev_work->fdb_info.is_local))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!netif_running(dev))
|
if (!netif_running(dev))
|
||||||
|
@ -2971,7 +2972,7 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work)
|
||||||
switch (switchdev_work->event) {
|
switch (switchdev_work->event) {
|
||||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||||
fdb_info = &switchdev_work->fdb_info;
|
fdb_info = &switchdev_work->fdb_info;
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
break;
|
break;
|
||||||
err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
|
err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -2736,7 +2736,7 @@ static void rocker_switchdev_event_work(struct work_struct *work)
|
||||||
switch (switchdev_work->event) {
|
switch (switchdev_work->event) {
|
||||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||||
fdb_info = &switchdev_work->fdb_info;
|
fdb_info = &switchdev_work->fdb_info;
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
break;
|
break;
|
||||||
err = rocker_world_port_fdb_add(rocker_port, fdb_info);
|
err = rocker_world_port_fdb_add(rocker_port, fdb_info);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -2747,7 +2747,7 @@ static void rocker_switchdev_event_work(struct work_struct *work)
|
||||||
break;
|
break;
|
||||||
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
||||||
fdb_info = &switchdev_work->fdb_info;
|
fdb_info = &switchdev_work->fdb_info;
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
break;
|
break;
|
||||||
err = rocker_world_port_fdb_del(rocker_port, fdb_info);
|
err = rocker_world_port_fdb_del(rocker_port, fdb_info);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -385,7 +385,7 @@ static void am65_cpsw_switchdev_event_work(struct work_struct *work)
|
||||||
fdb->addr, fdb->vid, fdb->added_by_user,
|
fdb->addr, fdb->vid, fdb->added_by_user,
|
||||||
fdb->offloaded, port_id);
|
fdb->offloaded, port_id);
|
||||||
|
|
||||||
if (!fdb->added_by_user)
|
if (!fdb->added_by_user || fdb->is_local)
|
||||||
break;
|
break;
|
||||||
if (memcmp(port->slave.mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
if (memcmp(port->slave.mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
||||||
port_id = HOST_PORT_NUM;
|
port_id = HOST_PORT_NUM;
|
||||||
|
@ -401,7 +401,7 @@ static void am65_cpsw_switchdev_event_work(struct work_struct *work)
|
||||||
fdb->addr, fdb->vid, fdb->added_by_user,
|
fdb->addr, fdb->vid, fdb->added_by_user,
|
||||||
fdb->offloaded, port_id);
|
fdb->offloaded, port_id);
|
||||||
|
|
||||||
if (!fdb->added_by_user)
|
if (!fdb->added_by_user || fdb->is_local)
|
||||||
break;
|
break;
|
||||||
if (memcmp(port->slave.mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
if (memcmp(port->slave.mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
||||||
port_id = HOST_PORT_NUM;
|
port_id = HOST_PORT_NUM;
|
||||||
|
|
|
@ -395,7 +395,7 @@ static void cpsw_switchdev_event_work(struct work_struct *work)
|
||||||
fdb->addr, fdb->vid, fdb->added_by_user,
|
fdb->addr, fdb->vid, fdb->added_by_user,
|
||||||
fdb->offloaded, port);
|
fdb->offloaded, port);
|
||||||
|
|
||||||
if (!fdb->added_by_user)
|
if (!fdb->added_by_user || fdb->is_local)
|
||||||
break;
|
break;
|
||||||
if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
||||||
port = HOST_PORT_NUM;
|
port = HOST_PORT_NUM;
|
||||||
|
@ -411,7 +411,7 @@ static void cpsw_switchdev_event_work(struct work_struct *work)
|
||||||
fdb->addr, fdb->vid, fdb->added_by_user,
|
fdb->addr, fdb->vid, fdb->added_by_user,
|
||||||
fdb->offloaded, port);
|
fdb->offloaded, port);
|
||||||
|
|
||||||
if (!fdb->added_by_user)
|
if (!fdb->added_by_user || fdb->is_local)
|
||||||
break;
|
break;
|
||||||
if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
|
||||||
port = HOST_PORT_NUM;
|
port = HOST_PORT_NUM;
|
||||||
|
|
|
@ -209,6 +209,7 @@ struct switchdev_notifier_fdb_info {
|
||||||
const unsigned char *addr;
|
const unsigned char *addr;
|
||||||
u16 vid;
|
u16 vid;
|
||||||
u8 added_by_user:1,
|
u8 added_by_user:1,
|
||||||
|
is_local:1,
|
||||||
offloaded:1;
|
offloaded:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,48 +107,28 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
|
|
||||||
u16 vid, struct net_device *dev,
|
|
||||||
bool added_by_user, bool offloaded)
|
|
||||||
{
|
|
||||||
struct switchdev_notifier_fdb_info info;
|
|
||||||
unsigned long notifier_type;
|
|
||||||
|
|
||||||
info.addr = mac;
|
|
||||||
info.vid = vid;
|
|
||||||
info.added_by_user = added_by_user;
|
|
||||||
info.offloaded = offloaded;
|
|
||||||
notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
|
|
||||||
call_switchdev_notifiers(notifier_type, dev, &info.info, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
|
br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
|
||||||
{
|
{
|
||||||
|
struct switchdev_notifier_fdb_info info = {
|
||||||
|
.addr = fdb->key.addr.addr,
|
||||||
|
.vid = fdb->key.vlan_id,
|
||||||
|
.added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags),
|
||||||
|
.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags),
|
||||||
|
.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags),
|
||||||
|
};
|
||||||
|
|
||||||
if (!fdb->dst)
|
if (!fdb->dst)
|
||||||
return;
|
return;
|
||||||
if (test_bit(BR_FDB_LOCAL, &fdb->flags))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RTM_DELNEIGH:
|
case RTM_DELNEIGH:
|
||||||
br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
|
call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE,
|
||||||
fdb->key.vlan_id,
|
fdb->dst->dev, &info.info, NULL);
|
||||||
fdb->dst->dev,
|
|
||||||
test_bit(BR_FDB_ADDED_BY_USER,
|
|
||||||
&fdb->flags),
|
|
||||||
test_bit(BR_FDB_OFFLOADED,
|
|
||||||
&fdb->flags));
|
|
||||||
break;
|
break;
|
||||||
case RTM_NEWNEIGH:
|
case RTM_NEWNEIGH:
|
||||||
br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
|
call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE,
|
||||||
fdb->key.vlan_id,
|
fdb->dst->dev, &info.info, NULL);
|
||||||
fdb->dst->dev,
|
|
||||||
test_bit(BR_FDB_ADDED_BY_USER,
|
|
||||||
&fdb->flags),
|
|
||||||
test_bit(BR_FDB_OFFLOADED,
|
|
||||||
&fdb->flags));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2329,7 +2329,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
|
||||||
fdb_info = ptr;
|
fdb_info = ptr;
|
||||||
|
|
||||||
if (dsa_slave_dev_check(dev)) {
|
if (dsa_slave_dev_check(dev)) {
|
||||||
if (!fdb_info->added_by_user)
|
if (!fdb_info->added_by_user || fdb_info->is_local)
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
|
|
||||||
dp = dsa_slave_to_port(dev);
|
dp = dsa_slave_to_port(dev);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче