net: dsa: add MDB support

Add SWITCHDEV_OBJ_ID_PORT_MDB support to the DSA layer.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vivien Didelot 2016-08-31 11:50:03 -04:00 committed by David S. Miller
parent dbeb714a5b
commit 8df3025520
3 changed files with 94 additions and 0 deletions

View File

@ -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
==== ====

View File

@ -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 {
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);

View File

@ -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,
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,
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,
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),