mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-21 05:14:52 +08:00
net: switchdev: merge switchdev_handle_fdb_{add,del}_to_device
To reduce code churn, the same patch makes multiple changes, since they all touch the same lines: 1. The implementations for these two are identical, just with different function pointers. Reduce duplications and name the function pointers "mod_cb" instead of "add_cb" and "del_cb". Pass the event as argument. 2. Drop the "const" attribute from "orig_dev". If the driver needs to check whether orig_dev belongs to itself and then call_switchdev_notifiers(orig_dev, SWITCHDEV_FDB_OFFLOADED), it can't, because call_switchdev_notifiers takes a non-const struct net_device *. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fab9eca884
commit
716a30a97a
@ -299,28 +299,16 @@ void switchdev_port_fwd_mark_set(struct net_device *dev,
|
||||
struct net_device *group_dev,
|
||||
bool joining);
|
||||
|
||||
int switchdev_handle_fdb_add_to_device(struct net_device *dev,
|
||||
int switchdev_handle_fdb_event_to_device(struct net_device *dev, unsigned long event,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info));
|
||||
|
||||
int switchdev_handle_fdb_del_to_device(struct net_device *dev,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*lag_mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info));
|
||||
|
||||
int switchdev_handle_port_obj_add(struct net_device *dev,
|
||||
@ -426,32 +414,16 @@ call_switchdev_blocking_notifiers(unsigned long val,
|
||||
}
|
||||
|
||||
static inline int
|
||||
switchdev_handle_fdb_add_to_device(struct net_device *dev,
|
||||
switchdev_handle_fdb_event_to_device(struct net_device *dev, unsigned long event,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
switchdev_handle_fdb_del_to_device(struct net_device *dev,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*lag_mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info))
|
||||
{
|
||||
return 0;
|
||||
|
@ -2468,10 +2468,9 @@ static bool dsa_foreign_dev_check(const struct net_device *dev,
|
||||
}
|
||||
|
||||
static int dsa_slave_fdb_event(struct net_device *dev,
|
||||
const struct net_device *orig_dev,
|
||||
const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
unsigned long event)
|
||||
struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info)
|
||||
{
|
||||
struct dsa_switchdev_event_work *switchdev_work;
|
||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
@ -2525,24 +2524,6 @@ static int dsa_slave_fdb_event(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dsa_slave_fdb_add_to_device(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info)
|
||||
{
|
||||
return dsa_slave_fdb_event(dev, orig_dev, ctx, fdb_info,
|
||||
SWITCHDEV_FDB_ADD_TO_DEVICE);
|
||||
}
|
||||
|
||||
static int
|
||||
dsa_slave_fdb_del_to_device(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info)
|
||||
{
|
||||
return dsa_slave_fdb_event(dev, orig_dev, ctx, fdb_info,
|
||||
SWITCHDEV_FDB_DEL_TO_DEVICE);
|
||||
}
|
||||
|
||||
/* Called under rcu_read_lock() */
|
||||
static int dsa_slave_switchdev_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr)
|
||||
@ -2557,18 +2538,12 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
|
||||
dsa_slave_port_attr_set);
|
||||
return notifier_from_errno(err);
|
||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||
err = switchdev_handle_fdb_add_to_device(dev, ptr,
|
||||
dsa_slave_dev_check,
|
||||
dsa_foreign_dev_check,
|
||||
dsa_slave_fdb_add_to_device,
|
||||
NULL);
|
||||
return notifier_from_errno(err);
|
||||
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
||||
err = switchdev_handle_fdb_del_to_device(dev, ptr,
|
||||
dsa_slave_dev_check,
|
||||
dsa_foreign_dev_check,
|
||||
dsa_slave_fdb_del_to_device,
|
||||
NULL);
|
||||
err = switchdev_handle_fdb_event_to_device(dev, event, ptr,
|
||||
dsa_slave_dev_check,
|
||||
dsa_foreign_dev_check,
|
||||
dsa_slave_fdb_event,
|
||||
NULL);
|
||||
return notifier_from_errno(err);
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
|
@ -428,17 +428,17 @@ switchdev_lower_dev_find(struct net_device *dev,
|
||||
return switchdev_priv.lower_dev;
|
||||
}
|
||||
|
||||
static int __switchdev_handle_fdb_add_to_device(struct net_device *dev,
|
||||
const struct net_device *orig_dev,
|
||||
static int __switchdev_handle_fdb_event_to_device(struct net_device *dev,
|
||||
struct net_device *orig_dev, unsigned long event,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*lag_mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info))
|
||||
{
|
||||
const struct switchdev_notifier_info *info = &fdb_info->info;
|
||||
@ -447,17 +447,17 @@ static int __switchdev_handle_fdb_add_to_device(struct net_device *dev,
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
if (check_cb(dev))
|
||||
return add_cb(dev, orig_dev, info->ctx, fdb_info);
|
||||
return mod_cb(dev, orig_dev, event, info->ctx, fdb_info);
|
||||
|
||||
if (netif_is_lag_master(dev)) {
|
||||
if (!switchdev_lower_dev_find(dev, check_cb, foreign_dev_check_cb))
|
||||
goto maybe_bridged_with_us;
|
||||
|
||||
/* This is a LAG interface that we offload */
|
||||
if (!lag_add_cb)
|
||||
if (!lag_mod_cb)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return lag_add_cb(dev, orig_dev, info->ctx, fdb_info);
|
||||
return lag_mod_cb(dev, orig_dev, event, info->ctx, fdb_info);
|
||||
}
|
||||
|
||||
/* Recurse through lower interfaces in case the FDB entry is pointing
|
||||
@ -481,10 +481,10 @@ static int __switchdev_handle_fdb_add_to_device(struct net_device *dev,
|
||||
foreign_dev_check_cb))
|
||||
continue;
|
||||
|
||||
err = __switchdev_handle_fdb_add_to_device(lower_dev, orig_dev,
|
||||
fdb_info, check_cb,
|
||||
foreign_dev_check_cb,
|
||||
add_cb, lag_add_cb);
|
||||
err = __switchdev_handle_fdb_event_to_device(lower_dev, orig_dev,
|
||||
event, fdb_info, check_cb,
|
||||
foreign_dev_check_cb,
|
||||
mod_cb, lag_mod_cb);
|
||||
if (err && err != -EOPNOTSUPP)
|
||||
return err;
|
||||
}
|
||||
@ -503,140 +503,34 @@ maybe_bridged_with_us:
|
||||
if (!switchdev_lower_dev_find(br, check_cb, foreign_dev_check_cb))
|
||||
return 0;
|
||||
|
||||
return __switchdev_handle_fdb_add_to_device(br, orig_dev, fdb_info,
|
||||
check_cb, foreign_dev_check_cb,
|
||||
add_cb, lag_add_cb);
|
||||
return __switchdev_handle_fdb_event_to_device(br, orig_dev, event, fdb_info,
|
||||
check_cb, foreign_dev_check_cb,
|
||||
mod_cb, lag_mod_cb);
|
||||
}
|
||||
|
||||
int switchdev_handle_fdb_add_to_device(struct net_device *dev,
|
||||
int switchdev_handle_fdb_event_to_device(struct net_device *dev, unsigned long event,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_add_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
int (*lag_mod_cb)(struct net_device *dev, struct net_device *orig_dev,
|
||||
unsigned long event, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info))
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __switchdev_handle_fdb_add_to_device(dev, dev, fdb_info,
|
||||
check_cb,
|
||||
foreign_dev_check_cb,
|
||||
add_cb, lag_add_cb);
|
||||
err = __switchdev_handle_fdb_event_to_device(dev, dev, event, fdb_info,
|
||||
check_cb, foreign_dev_check_cb,
|
||||
mod_cb, lag_mod_cb);
|
||||
if (err == -EOPNOTSUPP)
|
||||
err = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(switchdev_handle_fdb_add_to_device);
|
||||
|
||||
static int __switchdev_handle_fdb_del_to_device(struct net_device *dev,
|
||||
const struct net_device *orig_dev,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info))
|
||||
{
|
||||
const struct switchdev_notifier_info *info = &fdb_info->info;
|
||||
struct net_device *br, *lower_dev;
|
||||
struct list_head *iter;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
if (check_cb(dev))
|
||||
return del_cb(dev, orig_dev, info->ctx, fdb_info);
|
||||
|
||||
if (netif_is_lag_master(dev)) {
|
||||
if (!switchdev_lower_dev_find(dev, check_cb, foreign_dev_check_cb))
|
||||
goto maybe_bridged_with_us;
|
||||
|
||||
/* This is a LAG interface that we offload */
|
||||
if (!lag_del_cb)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return lag_del_cb(dev, orig_dev, info->ctx, fdb_info);
|
||||
}
|
||||
|
||||
/* Recurse through lower interfaces in case the FDB entry is pointing
|
||||
* towards a bridge device.
|
||||
*/
|
||||
if (netif_is_bridge_master(dev)) {
|
||||
if (!switchdev_lower_dev_find(dev, check_cb, foreign_dev_check_cb))
|
||||
return 0;
|
||||
|
||||
/* This is a bridge interface that we offload */
|
||||
netdev_for_each_lower_dev(dev, lower_dev, iter) {
|
||||
/* Do not propagate FDB entries across bridges */
|
||||
if (netif_is_bridge_master(lower_dev))
|
||||
continue;
|
||||
|
||||
/* Bridge ports might be either us, or LAG interfaces
|
||||
* that we offload.
|
||||
*/
|
||||
if (!check_cb(lower_dev) &&
|
||||
!switchdev_lower_dev_find(lower_dev, check_cb,
|
||||
foreign_dev_check_cb))
|
||||
continue;
|
||||
|
||||
err = __switchdev_handle_fdb_del_to_device(lower_dev, orig_dev,
|
||||
fdb_info, check_cb,
|
||||
foreign_dev_check_cb,
|
||||
del_cb, lag_del_cb);
|
||||
if (err && err != -EOPNOTSUPP)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
maybe_bridged_with_us:
|
||||
/* Event is neither on a bridge nor a LAG. Check whether it is on an
|
||||
* interface that is in a bridge with us.
|
||||
*/
|
||||
br = netdev_master_upper_dev_get_rcu(dev);
|
||||
if (!br || !netif_is_bridge_master(br))
|
||||
return 0;
|
||||
|
||||
if (!switchdev_lower_dev_find(br, check_cb, foreign_dev_check_cb))
|
||||
return 0;
|
||||
|
||||
return __switchdev_handle_fdb_del_to_device(br, orig_dev, fdb_info,
|
||||
check_cb, foreign_dev_check_cb,
|
||||
del_cb, lag_del_cb);
|
||||
}
|
||||
|
||||
int switchdev_handle_fdb_del_to_device(struct net_device *dev,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info,
|
||||
bool (*check_cb)(const struct net_device *dev),
|
||||
bool (*foreign_dev_check_cb)(const struct net_device *dev,
|
||||
const struct net_device *foreign_dev),
|
||||
int (*del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info),
|
||||
int (*lag_del_cb)(struct net_device *dev,
|
||||
const struct net_device *orig_dev, const void *ctx,
|
||||
const struct switchdev_notifier_fdb_info *fdb_info))
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __switchdev_handle_fdb_del_to_device(dev, dev, fdb_info,
|
||||
check_cb,
|
||||
foreign_dev_check_cb,
|
||||
del_cb, lag_del_cb);
|
||||
if (err == -EOPNOTSUPP)
|
||||
err = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(switchdev_handle_fdb_del_to_device);
|
||||
EXPORT_SYMBOL_GPL(switchdev_handle_fdb_event_to_device);
|
||||
|
||||
static int __switchdev_handle_port_obj_add(struct net_device *dev,
|
||||
struct switchdev_notifier_port_obj_info *port_obj_info,
|
||||
|
Loading…
Reference in New Issue
Block a user