Commit 05dd04b2 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

inetpeer: avoid false sharing in inet_peer_xrlim_allow()



Under DOS, inet_peer_xrlim_allow() might be called millions
of times per second from different cpus.

Make sure to write over peer->rate_tokens and peer->rate_last
only when really needed.

Note the inherent races of this function are still there,
we do not care of precise ICMP rate limiting.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20241219150330.3159027-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 710aebda
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -246,23 +246,27 @@ void inet_putpeer(struct inet_peer *p)
#define XRLIM_BURST_FACTOR 6
bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout)
{
	unsigned long now, token;
	unsigned long now, token, otoken, delta;
	bool rc = false;

	if (!peer)
		return true;

	token = peer->rate_tokens;
	token = otoken = READ_ONCE(peer->rate_tokens);
	now = jiffies;
	token += now - peer->rate_last;
	peer->rate_last = now;
	delta = now - READ_ONCE(peer->rate_last);
	if (delta) {
		WRITE_ONCE(peer->rate_last, now);
		token += delta;
		if (token > XRLIM_BURST_FACTOR * timeout)
			token = XRLIM_BURST_FACTOR * timeout;
	}
	if (token >= timeout) {
		token -= timeout;
		rc = true;
	}
	peer->rate_tokens = token;
	if (token != otoken)
		WRITE_ONCE(peer->rate_tokens, token);
	return rc;
}
EXPORT_SYMBOL(inet_peer_xrlim_allow);