[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190115194130.19896-13-f.fainelli@gmail.com>
Date: Tue, 15 Jan 2019 11:41:28 -0800
From: Florian Fainelli <f.fainelli@...il.com>
To: netdev@...r.kernel.org
Cc: Florian Fainelli <f.fainelli@...il.com>, andrew@...n.ch,
vivien.didelot@...il.com, davem@...emloft.net, idosch@...lanox.com,
jiri@...lanox.com, ilias.apalodimas@...aro.org,
ivan.khoronzhuk@...aro.org, roopa@...ulusnetworks.com,
nikolay@...ulusnetworks.com
Subject: [RFC net-next 12/14] net: dsa: Wire up multicast IGMP snooping attribute notification
The bridge can at runtime be configured with or without IGMP snooping
enabled but we were not processing the switchdev attribute that notifies
about that toggle, do this now.
Signed-off-by: Florian Fainelli <f.fainelli@...il.com>
---
include/net/dsa.h | 2 ++
net/dsa/dsa_priv.h | 11 +++++++++++
net/dsa/port.c | 13 +++++++++++++
net/dsa/slave.c | 4 ++++
net/dsa/switch.c | 28 ++++++++++++++++++++++++++++
5 files changed, 58 insertions(+)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index b3eefe8e18fd..11cd4db3bc9e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -479,6 +479,8 @@ struct dsa_switch_ops {
/*
* Multicast database
*/
+ int (*port_multicast_toggle)(struct dsa_switch *ds, int port,
+ bool mc_disabled);
int (*port_mdb_prepare)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
void (*port_mdb_add)(struct dsa_switch *ds, int port,
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index aad8acc70183..6f7ed2b3494f 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -27,6 +27,7 @@ enum {
DSA_NOTIFIER_VLAN_ADD,
DSA_NOTIFIER_VLAN_DEL,
DSA_NOTIFIER_VLAN_FILTERING,
+ DSA_NOTIFIER_MC_DISABLED,
};
/* DSA_NOTIFIER_AGEING_TIME */
@@ -74,6 +75,14 @@ struct dsa_notifier_vlan_filtering_info {
int port;
};
+/* DSA_NOTIFIER_MC_DISABLED */
+struct dsa_notifier_mc_disabled_info {
+ bool mc_disabled;
+ struct switchdev_trans *trans;
+ int sw_index;
+ int port;
+};
+
struct dsa_slave_priv {
/* Copy of CPU port xmit for faster access in slave transmit hot path */
struct sk_buff * (*xmit)(struct sk_buff *skb,
@@ -154,6 +163,8 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy);
void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy);
int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
+int dsa_port_multicast_toggle(struct dsa_port *dp, bool mc_disabled,
+ struct switchdev_trans *trans);
int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
struct switchdev_trans *trans);
int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index d7b057d46460..148458941b51 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -143,6 +143,19 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
}
+int dsa_port_multicast_toggle(struct dsa_port *dp, bool mc_disabled,
+ struct switchdev_trans *trans)
+{
+ struct dsa_notifier_mc_disabled_info info = {
+ .sw_index = dp->ds->index,
+ .port = dp->index,
+ .trans = trans,
+ .mc_disabled = mc_disabled,
+ };
+
+ return dsa_port_notify(dp, DSA_NOTIFIER_MC_DISABLED, &info);
+}
+
int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
struct switchdev_trans *trans)
{
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e266ef329583..acb7f1830e98 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -337,6 +337,10 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
ret = dsa_port_ageing_time(dp, attr->u.ageing_time, trans);
break;
+ case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
+ ret = dsa_port_multicast_toggle(dp, attr->u.mc_disabled,
+ trans);
+ break;
default:
ret = -EOPNOTSUPP;
break;
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 831334dc5e79..e095eb808434 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -261,6 +261,31 @@ static int dsa_switch_vlan_filtering(struct dsa_switch *ds,
return 0;
}
+static int dsa_switch_mc_disabled(struct dsa_switch *ds,
+ struct dsa_notifier_mc_disabled_info *info)
+{
+ struct switchdev_trans *trans = info->trans;
+ bool mc_disabled = info->mc_disabled;
+ int port = info->port;
+ int err;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return ds->ops->port_multicast_toggle ? 0 : -EOPNOTSUPP;
+
+ /* Build a mask of port members */
+ bitmap_zero(ds->bitmap, ds->num_ports);
+ if (ds->index == info->sw_index)
+ set_bit(port, ds->bitmap);
+
+ for_each_set_bit(port, ds->bitmap, ds->num_ports) {
+ err = ds->ops->port_multicast_toggle(ds, port, mc_disabled);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int dsa_switch_event(struct notifier_block *nb,
unsigned long event, void *info)
{
@@ -298,6 +323,9 @@ static int dsa_switch_event(struct notifier_block *nb,
case DSA_NOTIFIER_VLAN_FILTERING:
err = dsa_switch_vlan_filtering(ds, info);
break;
+ case DSA_NOTIFIER_MC_DISABLED:
+ err = dsa_switch_mc_disabled(ds, info);
+ break;
default:
err = -EOPNOTSUPP;
break;
--
2.17.1
Powered by blists - more mailing lists