net: switchdev: pass callback to dump operation
Similar to the notifier_call callback of a notifier_block, change the function signature of switchdev dump operation to: int switchdev_port_obj_dump(struct net_device *dev, enum switchdev_obj_id id, void *obj, int (*cb)(void *obj)); This allows the caller to pass and expect back a specific switchdev_obj_* structure instead of the generic switchdev_obj one. Drivers implementation of dump operation can now expect this specific structure and call the callback with it. Drivers have been changed accordingly. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
03d5fb1862
commit
25f07adc47
|
@ -4538,10 +4538,10 @@ static int rocker_port_obj_del(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
|
static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
|
||||||
struct switchdev_obj *obj)
|
struct switchdev_obj_fdb *fdb,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
struct rocker *rocker = rocker_port->rocker;
|
struct rocker *rocker = rocker_port->rocker;
|
||||||
struct switchdev_obj_fdb *fdb = &obj->u.fdb;
|
|
||||||
struct rocker_fdb_tbl_entry *found;
|
struct rocker_fdb_tbl_entry *found;
|
||||||
struct hlist_node *tmp;
|
struct hlist_node *tmp;
|
||||||
unsigned long lock_flags;
|
unsigned long lock_flags;
|
||||||
|
@ -4556,7 +4556,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
|
||||||
fdb->ndm_state = NUD_REACHABLE;
|
fdb->ndm_state = NUD_REACHABLE;
|
||||||
fdb->vid = rocker_port_vlan_to_vid(rocker_port,
|
fdb->vid = rocker_port_vlan_to_vid(rocker_port,
|
||||||
found->key.vlan_id);
|
found->key.vlan_id);
|
||||||
err = obj->cb(obj);
|
err = cb(fdb);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4566,9 +4566,9 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
|
static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
|
||||||
struct switchdev_obj *obj)
|
struct switchdev_obj_vlan *vlan,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
struct switchdev_obj_vlan *vlan = &obj->u.vlan;
|
|
||||||
u16 vid;
|
u16 vid;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -4579,7 +4579,7 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
|
||||||
if (rocker_vlan_id_is_internal(htons(vid)))
|
if (rocker_vlan_id_is_internal(htons(vid)))
|
||||||
vlan->flags |= BRIDGE_VLAN_INFO_PVID;
|
vlan->flags |= BRIDGE_VLAN_INFO_PVID;
|
||||||
vlan->vid_begin = vlan->vid_end = vid;
|
vlan->vid_begin = vlan->vid_end = vid;
|
||||||
err = obj->cb(obj);
|
err = cb(vlan);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4588,17 +4588,18 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rocker_port_obj_dump(struct net_device *dev,
|
static int rocker_port_obj_dump(struct net_device *dev,
|
||||||
struct switchdev_obj *obj)
|
enum switchdev_obj_id id, void *obj,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
const struct rocker_port *rocker_port = netdev_priv(dev);
|
const struct rocker_port *rocker_port = netdev_priv(dev);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
switch (obj->id) {
|
switch (id) {
|
||||||
case SWITCHDEV_OBJ_PORT_FDB:
|
case SWITCHDEV_OBJ_PORT_FDB:
|
||||||
err = rocker_port_fdb_dump(rocker_port, obj);
|
err = rocker_port_fdb_dump(rocker_port, obj, cb);
|
||||||
break;
|
break;
|
||||||
case SWITCHDEV_OBJ_PORT_VLAN:
|
case SWITCHDEV_OBJ_PORT_VLAN:
|
||||||
err = rocker_port_vlan_dump(rocker_port, obj);
|
err = rocker_port_vlan_dump(rocker_port, obj, cb);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
|
|
|
@ -120,7 +120,8 @@ struct switchdev_ops {
|
||||||
int (*switchdev_port_obj_del)(struct net_device *dev,
|
int (*switchdev_port_obj_del)(struct net_device *dev,
|
||||||
struct switchdev_obj *obj);
|
struct switchdev_obj *obj);
|
||||||
int (*switchdev_port_obj_dump)(struct net_device *dev,
|
int (*switchdev_port_obj_dump)(struct net_device *dev,
|
||||||
struct switchdev_obj *obj);
|
enum switchdev_obj_id id, void *obj,
|
||||||
|
int (*cb)(void *obj));
|
||||||
};
|
};
|
||||||
|
|
||||||
enum switchdev_notifier_type {
|
enum switchdev_notifier_type {
|
||||||
|
@ -152,7 +153,8 @@ int switchdev_port_attr_set(struct net_device *dev,
|
||||||
struct switchdev_attr *attr);
|
struct switchdev_attr *attr);
|
||||||
int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj);
|
int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj);
|
||||||
int switchdev_port_obj_del(struct net_device *dev, struct switchdev_obj *obj);
|
int switchdev_port_obj_del(struct net_device *dev, struct switchdev_obj *obj);
|
||||||
int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj);
|
int switchdev_port_obj_dump(struct net_device *dev, enum switchdev_obj_id id,
|
||||||
|
void *obj, int (*cb)(void *obj));
|
||||||
int register_switchdev_notifier(struct notifier_block *nb);
|
int register_switchdev_notifier(struct notifier_block *nb);
|
||||||
int unregister_switchdev_notifier(struct notifier_block *nb);
|
int unregister_switchdev_notifier(struct notifier_block *nb);
|
||||||
int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
|
int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
|
||||||
|
@ -209,7 +211,8 @@ static inline int switchdev_port_obj_del(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int switchdev_port_obj_dump(struct net_device *dev,
|
static inline int switchdev_port_obj_dump(struct net_device *dev,
|
||||||
struct switchdev_obj *obj)
|
enum switchdev_obj_id id, void *obj,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,9 +300,9 @@ static int dsa_slave_port_vlan_del(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_port_vlan_dump(struct net_device *dev,
|
static int dsa_slave_port_vlan_dump(struct net_device *dev,
|
||||||
struct switchdev_obj *obj)
|
struct switchdev_obj_vlan *vlan,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
struct switchdev_obj_vlan *vlan = &obj->u.vlan;
|
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct dsa_switch *ds = p->parent;
|
struct dsa_switch *ds = p->parent;
|
||||||
DECLARE_BITMAP(members, DSA_MAX_PORTS);
|
DECLARE_BITMAP(members, DSA_MAX_PORTS);
|
||||||
|
@ -334,7 +334,7 @@ static int dsa_slave_port_vlan_dump(struct net_device *dev,
|
||||||
if (test_bit(p->port, untagged))
|
if (test_bit(p->port, untagged))
|
||||||
vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
|
vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
|
||||||
|
|
||||||
err = obj->cb(obj);
|
err = cb(vlan);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -374,7 +374,8 @@ static int dsa_slave_port_fdb_del(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_port_fdb_dump(struct net_device *dev,
|
static int dsa_slave_port_fdb_dump(struct net_device *dev,
|
||||||
struct switchdev_obj *obj)
|
struct switchdev_obj_fdb *fdb,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct dsa_switch *ds = p->parent;
|
struct dsa_switch *ds = p->parent;
|
||||||
|
@ -393,11 +394,11 @@ static int dsa_slave_port_fdb_dump(struct net_device *dev,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
obj->u.fdb.addr = addr;
|
fdb->addr = addr;
|
||||||
obj->u.fdb.vid = vid;
|
fdb->vid = vid;
|
||||||
obj->u.fdb.ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
|
fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
|
||||||
|
|
||||||
ret = obj->cb(obj);
|
ret = cb(fdb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -518,16 +519,17 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_port_obj_dump(struct net_device *dev,
|
static int dsa_slave_port_obj_dump(struct net_device *dev,
|
||||||
struct switchdev_obj *obj)
|
enum switchdev_obj_id id, void *obj,
|
||||||
|
int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
switch (obj->id) {
|
switch (id) {
|
||||||
case SWITCHDEV_OBJ_PORT_FDB:
|
case SWITCHDEV_OBJ_PORT_FDB:
|
||||||
err = dsa_slave_port_fdb_dump(dev, obj);
|
err = dsa_slave_port_fdb_dump(dev, obj, cb);
|
||||||
break;
|
break;
|
||||||
case SWITCHDEV_OBJ_PORT_VLAN:
|
case SWITCHDEV_OBJ_PORT_VLAN:
|
||||||
err = dsa_slave_port_vlan_dump(dev, obj);
|
err = dsa_slave_port_vlan_dump(dev, obj, cb);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
|
|
|
@ -386,9 +386,12 @@ EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
|
||||||
* switchdev_port_obj_dump - Dump port objects
|
* switchdev_port_obj_dump - Dump port objects
|
||||||
*
|
*
|
||||||
* @dev: port device
|
* @dev: port device
|
||||||
|
* @id: object ID
|
||||||
* @obj: object to dump
|
* @obj: object to dump
|
||||||
|
* @cb: function to call with a filled object
|
||||||
*/
|
*/
|
||||||
int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj)
|
int switchdev_port_obj_dump(struct net_device *dev, enum switchdev_obj_id id,
|
||||||
|
void *obj, int (*cb)(void *obj))
|
||||||
{
|
{
|
||||||
const struct switchdev_ops *ops = dev->switchdev_ops;
|
const struct switchdev_ops *ops = dev->switchdev_ops;
|
||||||
struct net_device *lower_dev;
|
struct net_device *lower_dev;
|
||||||
|
@ -396,7 +399,7 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj)
|
||||||
int err = -EOPNOTSUPP;
|
int err = -EOPNOTSUPP;
|
||||||
|
|
||||||
if (ops && ops->switchdev_port_obj_dump)
|
if (ops && ops->switchdev_port_obj_dump)
|
||||||
return ops->switchdev_port_obj_dump(dev, obj);
|
return ops->switchdev_port_obj_dump(dev, id, obj, cb);
|
||||||
|
|
||||||
/* Switch device port(s) may be stacked under
|
/* Switch device port(s) may be stacked under
|
||||||
* bond/team/vlan dev, so recurse down to dump objects on
|
* bond/team/vlan dev, so recurse down to dump objects on
|
||||||
|
@ -404,7 +407,7 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
netdev_for_each_lower_dev(dev, lower_dev, iter) {
|
netdev_for_each_lower_dev(dev, lower_dev, iter) {
|
||||||
err = switchdev_port_obj_dump(lower_dev, obj);
|
err = switchdev_port_obj_dump(lower_dev, id, obj, cb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +479,7 @@ int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
|
||||||
EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
|
EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
|
||||||
|
|
||||||
struct switchdev_vlan_dump {
|
struct switchdev_vlan_dump {
|
||||||
struct switchdev_obj obj;
|
struct switchdev_obj_vlan vlan;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u32 filter_mask;
|
u32 filter_mask;
|
||||||
u16 flags;
|
u16 flags;
|
||||||
|
@ -514,11 +517,11 @@ static int switchdev_port_vlan_dump_put(struct switchdev_vlan_dump *dump)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int switchdev_port_vlan_dump_cb(struct switchdev_obj *obj)
|
static int switchdev_port_vlan_dump_cb(void *obj)
|
||||||
{
|
{
|
||||||
|
struct switchdev_obj_vlan *vlan = obj;
|
||||||
struct switchdev_vlan_dump *dump =
|
struct switchdev_vlan_dump *dump =
|
||||||
container_of(obj, struct switchdev_vlan_dump, obj);
|
container_of(vlan, struct switchdev_vlan_dump, vlan);
|
||||||
struct switchdev_obj_vlan *vlan = &dump->obj.u.vlan;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (vlan->vid_begin > vlan->vid_end)
|
if (vlan->vid_begin > vlan->vid_end)
|
||||||
|
@ -570,10 +573,6 @@ static int switchdev_port_vlan_fill(struct sk_buff *skb, struct net_device *dev,
|
||||||
u32 filter_mask)
|
u32 filter_mask)
|
||||||
{
|
{
|
||||||
struct switchdev_vlan_dump dump = {
|
struct switchdev_vlan_dump dump = {
|
||||||
.obj = {
|
|
||||||
.id = SWITCHDEV_OBJ_PORT_VLAN,
|
|
||||||
.cb = switchdev_port_vlan_dump_cb,
|
|
||||||
},
|
|
||||||
.skb = skb,
|
.skb = skb,
|
||||||
.filter_mask = filter_mask,
|
.filter_mask = filter_mask,
|
||||||
};
|
};
|
||||||
|
@ -581,7 +580,9 @@ static int switchdev_port_vlan_fill(struct sk_buff *skb, struct net_device *dev,
|
||||||
|
|
||||||
if ((filter_mask & RTEXT_FILTER_BRVLAN) ||
|
if ((filter_mask & RTEXT_FILTER_BRVLAN) ||
|
||||||
(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
|
(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
|
||||||
err = switchdev_port_obj_dump(dev, &dump.obj);
|
err = switchdev_port_obj_dump(dev, SWITCHDEV_OBJ_PORT_VLAN,
|
||||||
|
&dump.vlan,
|
||||||
|
switchdev_port_vlan_dump_cb);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
|
if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
|
||||||
|
@ -856,17 +857,18 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
|
||||||
EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
|
EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
|
||||||
|
|
||||||
struct switchdev_fdb_dump {
|
struct switchdev_fdb_dump {
|
||||||
struct switchdev_obj obj;
|
struct switchdev_obj_fdb fdb;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct netlink_callback *cb;
|
struct netlink_callback *cb;
|
||||||
int idx;
|
int idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int switchdev_port_fdb_dump_cb(struct switchdev_obj *obj)
|
static int switchdev_port_fdb_dump_cb(void *obj)
|
||||||
{
|
{
|
||||||
|
struct switchdev_obj_fdb *fdb = obj;
|
||||||
struct switchdev_fdb_dump *dump =
|
struct switchdev_fdb_dump *dump =
|
||||||
container_of(obj, struct switchdev_fdb_dump, obj);
|
container_of(fdb, struct switchdev_fdb_dump, fdb);
|
||||||
u32 portid = NETLINK_CB(dump->cb->skb).portid;
|
u32 portid = NETLINK_CB(dump->cb->skb).portid;
|
||||||
u32 seq = dump->cb->nlh->nlmsg_seq;
|
u32 seq = dump->cb->nlh->nlmsg_seq;
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
|
@ -887,12 +889,12 @@ static int switchdev_port_fdb_dump_cb(struct switchdev_obj *obj)
|
||||||
ndm->ndm_flags = NTF_SELF;
|
ndm->ndm_flags = NTF_SELF;
|
||||||
ndm->ndm_type = 0;
|
ndm->ndm_type = 0;
|
||||||
ndm->ndm_ifindex = dump->dev->ifindex;
|
ndm->ndm_ifindex = dump->dev->ifindex;
|
||||||
ndm->ndm_state = obj->u.fdb.ndm_state;
|
ndm->ndm_state = fdb->ndm_state;
|
||||||
|
|
||||||
if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, obj->u.fdb.addr))
|
if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, fdb->addr))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (obj->u.fdb.vid && nla_put_u16(dump->skb, NDA_VLAN, obj->u.fdb.vid))
|
if (fdb->vid && nla_put_u16(dump->skb, NDA_VLAN, fdb->vid))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
nlmsg_end(dump->skb, nlh);
|
nlmsg_end(dump->skb, nlh);
|
||||||
|
@ -922,17 +924,14 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
||||||
struct net_device *filter_dev, int idx)
|
struct net_device *filter_dev, int idx)
|
||||||
{
|
{
|
||||||
struct switchdev_fdb_dump dump = {
|
struct switchdev_fdb_dump dump = {
|
||||||
.obj = {
|
|
||||||
.id = SWITCHDEV_OBJ_PORT_FDB,
|
|
||||||
.cb = switchdev_port_fdb_dump_cb,
|
|
||||||
},
|
|
||||||
.dev = dev,
|
.dev = dev,
|
||||||
.skb = skb,
|
.skb = skb,
|
||||||
.cb = cb,
|
.cb = cb,
|
||||||
.idx = idx,
|
.idx = idx,
|
||||||
};
|
};
|
||||||
|
|
||||||
switchdev_port_obj_dump(dev, &dump.obj);
|
switchdev_port_obj_dump(dev, SWITCHDEV_OBJ_PORT_FDB, &dump.fdb,
|
||||||
|
switchdev_port_fdb_dump_cb);
|
||||||
return dump.idx;
|
return dump.idx;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
|
EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
|
||||||
|
|
Loading…
Reference in New Issue