A system/cpu can be loaded by a hacker with flooding of broadcast or
multicast packets, to prevent this some Ethernet controllers like CPSW
provide a mechanism to limit the broadcast/multicast packet rate via
hardware limiters. This patch series enables this feature via
Ethtool Coalesce.
Mugunthan V N (3):
net: ethtool: Add Multicast and broadcast rate limit coalescing
feature
drivers: net: cpsw: remove redundancy check
drivers: net: cpsw: Add support for multicast/broadcast rate limit
drivers/net/ethernet/ti/cpsw.c | 83 +++++++++++++++++++++++++++++++++++++++---
include/uapi/linux/ethtool.h | 4 ++
2 files changed, 82 insertions(+), 5 deletions(-)
--
2.0.0.390.gcb682f8
Add ability to limit the broadcast or multicast packets to prevent
the loading of the CPU by a hacker with a broadcast or multicast
packet flood.
Signed-off-by: Mugunthan V N <[email protected]>
---
include/uapi/linux/ethtool.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index e3c7a71..96ade34 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -350,6 +350,8 @@ struct ethtool_modinfo {
* a TX interrupt, when the packet rate is above @pkt_rate_high.
* @rate_sample_interval: How often to do adaptive coalescing packet rate
* sampling, measured in seconds. Must not be zero.
+ * @rx_max_mcast: Threshold for high multicast packet rate (packets per second)
+ * @rx_max_bcast: Threshold for high broadcast packet rate (packets per second)
*
* Each pair of (usecs, max_frames) fields specifies that interrupts
* should be coalesced until
@@ -400,6 +402,8 @@ struct ethtool_coalesce {
__u32 tx_coalesce_usecs_high;
__u32 tx_max_coalesced_frames_high;
__u32 rate_sample_interval;
+ __u32 rx_max_mcast;
+ __u32 rx_max_bcast;
};
/**
--
2.0.0.390.gcb682f8
Add support for multicast/broadcast rate limit feature via ethtool coalesce.
Signed-off-by: Mugunthan V N <[email protected]>
---
drivers/net/ethernet/ti/cpsw.c | 80 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 78 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a6117e6..2a984e6 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -403,6 +403,8 @@ struct cpsw_priv {
bool irq_enabled;
struct cpts *cpts;
u32 emac_port;
+ u32 rx_max_mcast;
+ u32 rx_max_bcast;
};
struct cpsw_stats {
@@ -871,11 +873,13 @@ static int cpsw_get_coalesce(struct net_device *ndev,
struct cpsw_priv *priv = netdev_priv(ndev);
coal->rx_coalesce_usecs = priv->coal_intvl;
+ coal->rx_max_mcast = priv->rx_max_mcast;
+ coal->rx_max_bcast = priv->rx_max_bcast;
return 0;
}
-static int cpsw_set_coalesce(struct net_device *ndev,
- struct ethtool_coalesce *coal)
+static int cpsw_set_coalesce_usecs(struct net_device *ndev,
+ struct ethtool_coalesce *coal)
{
struct cpsw_priv *priv = netdev_priv(ndev);
u32 int_ctrl;
@@ -933,6 +937,74 @@ static int cpsw_set_coalesce(struct net_device *ndev,
return 0;
}
+static int cpsw_set_coalesce_mcast(struct net_device *ndev,
+ struct ethtool_coalesce *coal)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ int port;
+
+ priv->rx_max_mcast = coal->rx_max_mcast;
+
+ if (priv->data.dual_emac)
+ port = priv->emac_port;
+ else
+ port = priv->data.active_slave;
+
+ cpsw_ale_control_set(priv->ale, port, ALE_PORT_MCAST_LIMIT,
+ coal->rx_max_mcast);
+
+ dev_dbg(priv->dev, "rx_max_mcast set to %d\n", priv->rx_max_mcast);
+ return 0;
+}
+
+static int cpsw_set_coalesce_bcast(struct net_device *ndev,
+ struct ethtool_coalesce *coal)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ int port;
+
+ priv->rx_max_bcast = coal->rx_max_bcast;
+
+ if (priv->data.dual_emac)
+ port = priv->emac_port + 1;
+ else
+ port = priv->data.active_slave + 1;
+
+ cpsw_ale_control_set(priv->ale, port, ALE_PORT_BCAST_LIMIT,
+ coal->rx_max_bcast);
+
+ dev_dbg(priv->dev, "rx_max_mcast set to %d\n", priv->rx_max_bcast);
+ return 0;
+}
+
+static int cpsw_set_coalesce(struct net_device *ndev,
+ struct ethtool_coalesce *coal)
+{
+ int ret = -EINVAL;
+
+ if (coal->rx_coalesce_usecs) {
+ ret = cpsw_set_coalesce_usecs(ndev, coal);
+ if (ret) {
+ dev_err(&ndev->dev, "set rx-usecs failed\n");
+ return ret;
+ }
+ }
+
+ ret = cpsw_set_coalesce_mcast(ndev, coal);
+ if (ret) {
+ dev_err(&ndev->dev, "set coalesce rx-max-mcast failed\n");
+ return ret;
+ }
+
+ ret = cpsw_set_coalesce_bcast(ndev, coal);
+ if (ret) {
+ dev_err(&ndev->dev, "set coalesce rx-max-bcast failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
static int cpsw_get_sset_count(struct net_device *ndev, int sset)
{
switch (sset) {
@@ -1227,6 +1299,10 @@ static int cpsw_ndo_open(struct net_device *ndev)
/* enable statistics collection only on all ports */
__raw_writel(0x7, &priv->regs->stat_port_en);
+ /* Enable rate limit feature in the switch for rx only */
+ cpsw_ale_control_set(priv->ale, 0, ALE_RATE_LIMIT, 1);
+ cpsw_ale_control_set(priv->ale, 0, ALE_RATE_LIMIT_TX, 0);
+
if (WARN_ON(!priv->data.rx_descs))
priv->data.rx_descs = 128;
--
2.0.0.390.gcb682f8
In cpsw_set_coalesce, rx_coalesce_usecs is already checked before
calling this function, so removing redundancy check.
Signed-off-by: Mugunthan V N <[email protected]>
---
drivers/net/ethernet/ti/cpsw.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b988d16..a6117e6 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -884,9 +884,6 @@ static int cpsw_set_coalesce(struct net_device *ndev,
u32 addnl_dvdr = 1;
u32 coal_intvl = 0;
- if (!coal->rx_coalesce_usecs)
- return -EINVAL;
-
coal_intvl = coal->rx_coalesce_usecs;
int_ctrl = readl(&priv->wr_regs->int_control);
--
2.0.0.390.gcb682f8
On Wed, 9 Jul 2014, Mugunthan V N wrote:
> Add support for multicast/broadcast rate limit feature via ethtool coalesce.
>
> Signed-off-by: Mugunthan V N <[email protected]>
> ---
> drivers/net/ethernet/ti/cpsw.c | 80 ++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 78 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index a6117e6..2a984e6 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -403,6 +403,8 @@ struct cpsw_priv {
> bool irq_enabled;
> struct cpts *cpts;
> u32 emac_port;
> + u32 rx_max_mcast;
> + u32 rx_max_bcast;
> };
>
> struct cpsw_stats {
> @@ -871,11 +873,13 @@ static int cpsw_get_coalesce(struct net_device *ndev,
> struct cpsw_priv *priv = netdev_priv(ndev);
>
> coal->rx_coalesce_usecs = priv->coal_intvl;
> + coal->rx_max_mcast = priv->rx_max_mcast;
> + coal->rx_max_bcast = priv->rx_max_bcast;
> return 0;
> }
>
> -static int cpsw_set_coalesce(struct net_device *ndev,
> - struct ethtool_coalesce *coal)
> +static int cpsw_set_coalesce_usecs(struct net_device *ndev,
> + struct ethtool_coalesce *coal)
> {
> struct cpsw_priv *priv = netdev_priv(ndev);
> u32 int_ctrl;
> @@ -933,6 +937,74 @@ static int cpsw_set_coalesce(struct net_device *ndev,
> return 0;
> }
>
> +static int cpsw_set_coalesce_mcast(struct net_device *ndev,
> + struct ethtool_coalesce *coal)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> + int port;
> +
> + priv->rx_max_mcast = coal->rx_max_mcast;
> +
> + if (priv->data.dual_emac)
> + port = priv->emac_port;
> + else
> + port = priv->data.active_slave;
> +
> + cpsw_ale_control_set(priv->ale, port, ALE_PORT_MCAST_LIMIT,
> + coal->rx_max_mcast);
> +
> + dev_dbg(priv->dev, "rx_max_mcast set to %d\n", priv->rx_max_mcast);
> + return 0;
> +}
> +
> +static int cpsw_set_coalesce_bcast(struct net_device *ndev,
> + struct ethtool_coalesce *coal)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> + int port;
> +
> + priv->rx_max_bcast = coal->rx_max_bcast;
> +
> + if (priv->data.dual_emac)
> + port = priv->emac_port + 1;
> + else
> + port = priv->data.active_slave + 1;
> +
> + cpsw_ale_control_set(priv->ale, port, ALE_PORT_BCAST_LIMIT,
> + coal->rx_max_bcast);
Both cpsw_set_coalesce_bcast & cpsw_set_coalesce_mcast always return 0.
May be you can return result of cpsw_ale_control_set()?
> +
> + dev_dbg(priv->dev, "rx_max_mcast set to %d\n", priv->rx_max_bcast);
> + return 0;
> +}
> +
> +static int cpsw_set_coalesce(struct net_device *ndev,
> + struct ethtool_coalesce *coal)
> +{
> + int ret = -EINVAL;
> +
> + if (coal->rx_coalesce_usecs) {
> + ret = cpsw_set_coalesce_usecs(ndev, coal);
> + if (ret) {
> + dev_err(&ndev->dev, "set rx-usecs failed\n");
> + return ret;
> + }
> + }
> +
> + ret = cpsw_set_coalesce_mcast(ndev, coal);
> + if (ret) {
> + dev_err(&ndev->dev, "set coalesce rx-max-mcast failed\n");
> + return ret;
> + }
So that ret check here will be meaningful.
thanks
> +
> + ret = cpsw_set_coalesce_bcast(ndev, coal);
> + if (ret) {
> + dev_err(&ndev->dev, "set coalesce rx-max-bcast failed\n");
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> static int cpsw_get_sset_count(struct net_device *ndev, int sset)
> {
> switch (sset) {
> @@ -1227,6 +1299,10 @@ static int cpsw_ndo_open(struct net_device *ndev)
> /* enable statistics collection only on all ports */
> __raw_writel(0x7, &priv->regs->stat_port_en);
>
> + /* Enable rate limit feature in the switch for rx only */
> + cpsw_ale_control_set(priv->ale, 0, ALE_RATE_LIMIT, 1);
> + cpsw_ale_control_set(priv->ale, 0, ALE_RATE_LIMIT_TX, 0);
> +
> if (WARN_ON(!priv->data.rx_descs))
> priv->data.rx_descs = 128;
>
> --
> 2.0.0.390.gcb682f8
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
From: Mugunthan V N <[email protected]>
Date: Wed, 9 Jul 2014 12:44:07 +0530
> A system/cpu can be loaded by a hacker with flooding of broadcast or
> multicast packets, to prevent this some Ethernet controllers like CPSW
> provide a mechanism to limit the broadcast/multicast packet rate via
> hardware limiters. This patch series enables this feature via
> Ethtool Coalesce.
This is pretty bogus if you ask me.
What is the difference from accepting a high rate of unicast packets?
I say it is no different.
Therefore, this feature makes no sense to me at all.
On Thursday 10 July 2014 05:14 AM, David Miller wrote:
> From: Mugunthan V N <[email protected]>
> Date: Wed, 9 Jul 2014 12:44:07 +0530
>
>> A system/cpu can be loaded by a hacker with flooding of broadcast or
>> multicast packets, to prevent this some Ethernet controllers like CPSW
>> provide a mechanism to limit the broadcast/multicast packet rate via
>> hardware limiters. This patch series enables this feature via
>> Ethtool Coalesce.
> This is pretty bogus if you ask me.
>
> What is the difference from accepting a high rate of unicast packets?
> I say it is no different.
>
> Therefore, this feature makes no sense to me at all.
Any packet storm can cause an endpoint some issues. Typically packet
storms will cause the system CPU to thrash resulting is very low system
performance.
Unicast storms only target a single destination end station, it can be
easily mitigated by the host adding a blocking entry in the LUT for each
aggressor.
Broadcast and multicast target multiple end stations, or an entire
network, not only can it cause CPU thrashing, it can result in loss of
other broadcast and multicast services. The rate limiting feature allow
the broadcast and or multicast traffic to be dropped if the rates are
too high. This eliminates the CPU thrashing issue. It also allows the
system to analyze the aggressors and block them for future transgressions.
Regards
Mugunthan V N
> From: Mugunthan V N
> On Thursday 10 July 2014 05:14 AM, David Miller wrote:
> > From: Mugunthan V N <[email protected]>
> > Date: Wed, 9 Jul 2014 12:44:07 +0530
> >
> >> A system/cpu can be loaded by a hacker with flooding of broadcast or
> >> multicast packets, to prevent this some Ethernet controllers like CPSW
> >> provide a mechanism to limit the broadcast/multicast packet rate via
> >> hardware limiters. This patch series enables this feature via
> >> Ethtool Coalesce.
> > This is pretty bogus if you ask me.
> >
> > What is the difference from accepting a high rate of unicast packets?
> > I say it is no different.
> >
> > Therefore, this feature makes no sense to me at all.
>
> Any packet storm can cause an endpoint some issues. Typically packet
> storms will cause the system CPU to thrash resulting is very low system
> performance.
>
> Unicast storms only target a single destination end station, it can be
> easily mitigated by the host adding a blocking entry in the LUT for each
> aggressor.
>
> Broadcast and multicast target multiple end stations, or an entire
> network, not only can it cause CPU thrashing, it can result in loss of
> other broadcast and multicast services. The rate limiting feature allow
> the broadcast and or multicast traffic to be dropped if the rates are
> too high. This eliminates the CPU thrashing issue. It also allows the
> system to analyze the aggressors and block them for future transgressions.
Rate limiting multicast traffic will definitely cause the loss of multicast
services.
My experience of broadcast storms is that many of the ethernet switches
(probably especially the cheap ones) end up using a much slower software?
path for broadcasts. In a broadcast storm they start discarding normal
traffic - to point where a single ssh session becomes unusable.
This is true even when isolated from the storm by a 10M hub.
Broadcast storms are probably mostly caused by network topology issues.
Especially is switches are sending traffic to 'all ports' while resetting
the spanning tree tables.
David
On Thursday 17 July 2014 06:23 PM, David Laight wrote:
>> From: Mugunthan V N
>> On Thursday 10 July 2014 05:14 AM, David Miller wrote:
>>> From: Mugunthan V N <[email protected]>
>>> Date: Wed, 9 Jul 2014 12:44:07 +0530
>>>
>>>> A system/cpu can be loaded by a hacker with flooding of broadcast or
>>>> multicast packets, to prevent this some Ethernet controllers like CPSW
>>>> provide a mechanism to limit the broadcast/multicast packet rate via
>>>> hardware limiters. This patch series enables this feature via
>>>> Ethtool Coalesce.
>>> This is pretty bogus if you ask me.
>>>
>>> What is the difference from accepting a high rate of unicast packets?
>>> I say it is no different.
>>>
>>> Therefore, this feature makes no sense to me at all.
>> Any packet storm can cause an endpoint some issues. Typically packet
>> storms will cause the system CPU to thrash resulting is very low system
>> performance.
>>
>> Unicast storms only target a single destination end station, it can be
>> easily mitigated by the host adding a blocking entry in the LUT for each
>> aggressor.
>>
>> Broadcast and multicast target multiple end stations, or an entire
>> network, not only can it cause CPU thrashing, it can result in loss of
>> other broadcast and multicast services. The rate limiting feature allow
>> the broadcast and or multicast traffic to be dropped if the rates are
>> too high. This eliminates the CPU thrashing issue. It also allows the
>> system to analyze the aggressors and block them for future transgressions.
> Rate limiting multicast traffic will definitely cause the loss of multicast
> services.
When a system apply the rate limit, the system should expect to miss
some of the broadcast/multicast packet depending on the rate limit it
applies.
>
> My experience of broadcast storms is that many of the ethernet switches
> (probably especially the cheap ones) end up using a much slower software?
> path for broadcasts. In a broadcast storm they start discarding normal
> traffic - to point where a single ssh session becomes unusable.
> This is true even when isolated from the storm by a 10M hub.
>
> Broadcast storms are probably mostly caused by network topology issues.
> Especially is switches are sending traffic to 'all ports' while resetting
> the spanning tree tables.
>
This is one more example where broadcast/multicast rate limit can be used.
Regards
Mugunthan V N