Commit 8df30255 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller

net: dsa: add MDB support

Add SWITCHDEV_OBJ_ID_PORT_MDB support to the DSA layer.
Signed-off-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dbeb714a
...@@ -584,6 +584,29 @@ of DSA, would be the its port-based VLAN, used by the associated bridge device. ...@@ -584,6 +584,29 @@ of DSA, would be the its port-based VLAN, used by the associated bridge device.
function that the driver has to call for each MAC address known to be behind function that the driver has to call for each MAC address known to be behind
the given port. A switchdev object is used to carry the VID and FDB info. the given port. A switchdev object is used to carry the VID and FDB info.
- port_mdb_prepare: bridge layer function invoked when the bridge prepares the
installation of a multicast database entry. If the operation is not supported,
this function should return -EOPNOTSUPP to inform the bridge code to fallback
to a software implementation. No hardware setup must be done in this function.
See port_fdb_add for this and details.
- port_mdb_add: bridge layer function invoked when the bridge wants to install
a multicast database entry, the switch hardware should be programmed with the
specified address in the specified VLAN ID in the forwarding database
associated with this VLAN ID.
Note: VLAN ID 0 corresponds to the port private database, which, in the context
of DSA, would be the its port-based VLAN, used by the associated bridge device.
- port_mdb_del: bridge layer function invoked when the bridge wants to remove a
multicast database entry, the switch hardware should be programmed to delete
the specified MAC address from the specified VLAN ID if it was mapped into
this port forwarding database.
- port_mdb_dump: bridge layer function invoked with a switchdev callback
function that the driver has to call for each MAC address known to be behind
the given port. A switchdev object is used to carry the VID and MDB info.
TODO TODO
==== ====
......
...@@ -234,6 +234,7 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds) ...@@ -234,6 +234,7 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
struct switchdev_trans; struct switchdev_trans;
struct switchdev_obj; struct switchdev_obj;
struct switchdev_obj_port_fdb; struct switchdev_obj_port_fdb;
struct switchdev_obj_port_mdb;
struct switchdev_obj_port_vlan; struct switchdev_obj_port_vlan;
struct dsa_switch_ops { struct dsa_switch_ops {
...@@ -369,6 +370,21 @@ struct dsa_switch_ops { ...@@ -369,6 +370,21 @@ struct dsa_switch_ops {
int (*port_fdb_dump)(struct dsa_switch *ds, int port, int (*port_fdb_dump)(struct dsa_switch *ds, int port,
struct switchdev_obj_port_fdb *fdb, struct switchdev_obj_port_fdb *fdb,
int (*cb)(struct switchdev_obj *obj)); int (*cb)(struct switchdev_obj *obj));
/*
* Multicast database
*/
int (*port_mdb_prepare)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb,
struct switchdev_trans *trans);
void (*port_mdb_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb,
struct switchdev_trans *trans);
int (*port_mdb_del)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
int (*port_mdb_dump)(struct dsa_switch *ds, int port,
struct switchdev_obj_port_mdb *mdb,
int (*cb)(struct switchdev_obj *obj));
}; };
void register_switch_driver(struct dsa_switch_ops *type); void register_switch_driver(struct dsa_switch_ops *type);
......
...@@ -290,6 +290,50 @@ static int dsa_slave_port_fdb_dump(struct net_device *dev, ...@@ -290,6 +290,50 @@ static int dsa_slave_port_fdb_dump(struct net_device *dev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static int dsa_slave_port_mdb_add(struct net_device *dev,
const struct switchdev_obj_port_mdb *mdb,
struct switchdev_trans *trans)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->parent;
if (switchdev_trans_ph_prepare(trans)) {
if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
return -EOPNOTSUPP;
return ds->ops->port_mdb_prepare(ds, p->port, mdb, trans);
}
ds->ops->port_mdb_add(ds, p->port, mdb, trans);
return 0;
}
static int dsa_slave_port_mdb_del(struct net_device *dev,
const struct switchdev_obj_port_mdb *mdb)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->parent;
if (ds->ops->port_mdb_del)
return ds->ops->port_mdb_del(ds, p->port, mdb);
return -EOPNOTSUPP;
}
static int dsa_slave_port_mdb_dump(struct net_device *dev,
struct switchdev_obj_port_mdb *mdb,
switchdev_obj_dump_cb_t *cb)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->parent;
if (ds->ops->port_mdb_dump)
return ds->ops->port_mdb_dump(ds, p->port, mdb, cb);
return -EOPNOTSUPP;
}
static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_slave_priv *p = netdev_priv(dev);
...@@ -412,6 +456,10 @@ static int dsa_slave_port_obj_add(struct net_device *dev, ...@@ -412,6 +456,10 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
SWITCHDEV_OBJ_PORT_FDB(obj), SWITCHDEV_OBJ_PORT_FDB(obj),
trans); trans);
break; break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
err = dsa_slave_port_mdb_add(dev, SWITCHDEV_OBJ_PORT_MDB(obj),
trans);
break;
case SWITCHDEV_OBJ_ID_PORT_VLAN: case SWITCHDEV_OBJ_ID_PORT_VLAN:
err = dsa_slave_port_vlan_add(dev, err = dsa_slave_port_vlan_add(dev,
SWITCHDEV_OBJ_PORT_VLAN(obj), SWITCHDEV_OBJ_PORT_VLAN(obj),
...@@ -435,6 +483,9 @@ static int dsa_slave_port_obj_del(struct net_device *dev, ...@@ -435,6 +483,9 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
err = dsa_slave_port_fdb_del(dev, err = dsa_slave_port_fdb_del(dev,
SWITCHDEV_OBJ_PORT_FDB(obj)); SWITCHDEV_OBJ_PORT_FDB(obj));
break; break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
err = dsa_slave_port_mdb_del(dev, SWITCHDEV_OBJ_PORT_MDB(obj));
break;
case SWITCHDEV_OBJ_ID_PORT_VLAN: case SWITCHDEV_OBJ_ID_PORT_VLAN:
err = dsa_slave_port_vlan_del(dev, err = dsa_slave_port_vlan_del(dev,
SWITCHDEV_OBJ_PORT_VLAN(obj)); SWITCHDEV_OBJ_PORT_VLAN(obj));
...@@ -459,6 +510,10 @@ static int dsa_slave_port_obj_dump(struct net_device *dev, ...@@ -459,6 +510,10 @@ static int dsa_slave_port_obj_dump(struct net_device *dev,
SWITCHDEV_OBJ_PORT_FDB(obj), SWITCHDEV_OBJ_PORT_FDB(obj),
cb); cb);
break; break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
err = dsa_slave_port_mdb_dump(dev, SWITCHDEV_OBJ_PORT_MDB(obj),
cb);
break;
case SWITCHDEV_OBJ_ID_PORT_VLAN: case SWITCHDEV_OBJ_ID_PORT_VLAN:
err = dsa_slave_port_vlan_dump(dev, err = dsa_slave_port_vlan_dump(dev,
SWITCHDEV_OBJ_PORT_VLAN(obj), SWITCHDEV_OBJ_PORT_VLAN(obj),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment