mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andrew Lunn <andrew@lunn.ch>
To: David Yang <mmyangfl@gmail.com>
Cc: netdev@vger.kernel.org, Vladimir Oltean <olteanv@gmail.com>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next 2/3] net: dsa: yt921x: Add port police support
Date: Wed, 25 Feb 2026 15:17:38 +0100	[thread overview]
Message-ID: <8be7610c-c606-4c7d-8c8b-b2873bed082e@lunn.ch> (raw)
In-Reply-To: <20260225090853.2021140-3-mmyangfl@gmail.com>

> +static void u32a_update_u64(u32 *arr, u64 mask, u64 val)
> +{
> +	arr[0] &= ~((u32)mask);
> +	arr[1] &= ~((u32)(mask >> 32));
> +	arr[0] |= (u32)val;
> +	arr[1] |= (u32)(val >> 32);
> +}

The name of this function is not helping me understand what it
actually does.

> +/* v * 2^e */
> +#define ldexpi(v, e) ({ \
> +	__auto_type _v = (v); \
> +	__auto_type _e = (e); \
> +	_e >= 0 ? _v << _e : _v >> -_e; \
> +})
> +
> +/* slot (ns) * rate (/s) / 10^9 (ns/s) = 2^C * token * 4^unit */
> +#define rate2token(rate, unit, slot_ns, C) \
> +	((u32)(ldexpi((slot_ns) * (rate), \
> +		      -(2 * (unit) + (C) + YT921X_TOKEN_RATE_C)) / 1000000000))
> +#define token2rate(token, unit, slot_ns, C) \
> +	(ldexpi(1000000000 * (u64)(token), \
> +		2 * (unit) + (C) + YT921X_TOKEN_RATE_C) / (slot_ns))
> +
> +/* burst = 2^C * token * 4^unit */
> +#define burst2token(burst, unit, C) ((u32)ldexpi((burst), -(2 * (unit) + (C))))
> +#define token2burst(token, unit, C) ldexpi((u64)(token), 2 * (unit) + (C))

Please avoid macros like this. Write functions. The compiler will
inline them if that makes sense. But you gain type checking, etc.

> +static struct yt921x_meter
> +yt921x_meter_tfm(struct yt921x_priv *priv, int port, unsigned int slot_ns,
> +		 u64 rate, u64 burst, unsigned int flags,
> +		 u32 cir_max, u32 cbs_max, int unit_max)
> +{
> +	const int C = flags & YT921X_METER_PKT_MODE ? YT921X_TOKEN_PKT_C :
> +		      YT921X_TOKEN_BYTE_C;
> +	struct device *dev = to_device(priv);
> +	struct yt921x_meter meter;
> +	bool distorted;
> +	u64 burst_est;
> +	u64 burst_max;
> +	u64 rate_max;
> +
> +	meter.unit = unit_max;
> +	rate_max = token2rate(cir_max, meter.unit, slot_ns, C);
> +	burst_max = token2burst(cbs_max, meter.unit, C);
> +
> +	/* Clamp rate and burst */
> +	if (rate > rate_max || burst > burst_max) {
> +		dev_warn(dev,
> +			 "rate %llu, burst %llu too high, max is %llu, %llu, clamping...\n",
> +			 rate, burst, rate_max, burst_max);

I'm not sure clamping is the correct thing to do here. -ERANGE would
make it clearer that what the user requests is not possible.

> +
> +		if (rate > rate_max)
> +			rate = rate_max;
> +		if (burst > burst_max)
> +			burst = burst_max;
> +
> +		burst_est = slot_ns * rate / 1000000000;
> +	} else {
> +		u64 burst_sug;
> +
> +		burst_est = slot_ns * rate / 1000000000;
> +		burst_sug = burst_est;
> +		if (flags & YT921X_METER_PKT_MODE)
> +			burst_sug++;
> +		else
> +			burst_sug += ETH_HLEN + yt921x_mtu_fetch(priv, port) +
> +				     ETH_FCS_LEN;
> +		if (burst_sug > burst)
> +			dev_warn(dev,
> +				 "Consider burst at least %llu to match rate %llu\n",
> +				 burst_sug, rate);
> +
> +		/* Select unit */
> +		for (; meter.unit > 0; meter.unit--) {
> +			if (rate > (rate_max >> 2) || burst > (burst_max >> 2))
> +				break;
> +			rate_max >>= 2;
> +			burst_max >>= 2;
> +		}
> +	}
> +
> +	/* Calculate information rate and bucket size */
> +	distorted = false;
> +	meter.cir = rate2token(rate, meter.unit, slot_ns, C);
> +	if (!meter.cir) {
> +		distorted = true;
> +		meter.cir = 1;
> +	} else if (meter.cir > cir_max) {
> +		WARN_ON(1);
> +		meter.cir = cir_max;

What does this WARN_ON() indicate? If this fires, you want somebody
who is debugging it to be able to understand it.

> +	}
> +	meter.cbs = burst2token(burst, meter.unit, C);
> +	if (!meter.cbs) {
> +		distorted = true;
> +		meter.cbs = 1;
> +	} else if (meter.cbs > cbs_max) {
> +		WARN_ON(1);
> +		meter.cbs = cbs_max;
> +	}
> +	if (distorted)
> +		dev_warn(dev,
> +			 "Have to increase rate %llu, burst %llu to %llu, %llu\n",
> +			 rate, burst,
> +			 token2rate(meter.cir, meter.unit, slot_ns, C),
> +			 token2burst(meter.cbs, meter.unit, C));

I see a difference between clamping, and the granularity the hardware
can do. Clamping should be an error. However, rounding to what the
hardware can actually do is expected, so i would not spam the logs
with it.

> +static int
> +yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port,
> +			    const struct flow_action_police *policer)
> +{
> +	struct yt921x_priv *priv = to_yt921x_priv(ds);
> +	struct device *dev = to_device(priv);
> +	u32 ctrls[YT921X_METER_CTRL_S];
> +	struct yt921x_meter meter;
> +	bool pkt_mode;
> +	u64 burst;
> +	u64 rate;
> +	u32 ctrl;
> +	int res;
> +
> +	/* mtu defaults to unlimited but we got 2040 here, don't know why */
> +	if (policer->exceed.act_id != FLOW_ACTION_DROP ||
> +	    policer->notexceed.act_id != FLOW_ACTION_ACCEPT ||
> +	    policer->peakrate_bytes_ps || policer->avrate ||
> +	    policer->overhead) {
> +		dev_err(dev, "Unsupported options specified\n");

dev_dbg()

You might also want to extend .port_policer_add() to pass the extack
dsa_user_add_cls_matchall_police() has, so you can give a user
friendly error message.

	Andrew

  reply	other threads:[~2026-02-25 14:17 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-25  9:08 [PATCH net-next 0/3] net: dsa: yt921x: Add port police/tbf support David Yang
2026-02-25  9:08 ` [PATCH net-next 1/3] net: dsa: yt921x: Refactor long register helpers David Yang
2026-02-25 13:52   ` Andrew Lunn
2026-02-25 14:12     ` David Yang
2026-02-25 14:21       ` Andrew Lunn
2026-02-25  9:08 ` [PATCH net-next 2/3] net: dsa: yt921x: Add port police support David Yang
2026-02-25 14:17   ` Andrew Lunn [this message]
2026-02-25 14:47     ` David Yang
2026-02-25 15:06       ` Andrew Lunn
2026-02-25  9:08 ` [PATCH net-next 3/3] net: dsa: yt921x: Add port qdisc tbf support David Yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8be7610c-c606-4c7d-8c8b-b2873bed082e@lunn.ch \
    --to=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mmyangfl@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®