neighbor: fix proxy_delay usage when it is zero
authorBrian Haley <haleyb.dev@gmail.com>
Mon, 30 Jan 2023 17:14:28 +0000 (12:14 -0500)
committerJakub Kicinski <kuba@kernel.org>
Thu, 2 Feb 2023 05:02:54 +0000 (21:02 -0800)
When set to zero, the neighbor sysctl proxy_delay value
does not cause an immediate reply for ARP/ND requests
as expected, it instead causes a random delay between
[0, U32_MAX). Looking at this comment from
__get_random_u32_below() explains the reason:

/*
 * This function is technically undefined for ceil == 0, and in fact
 * for the non-underscored constant version in the header, we build bug
 * on that. But for the non-constant case, it's convenient to have that
 * evaluate to being a straight call to get_random_u32(), so that
 * get_random_u32_inclusive() can work over its whole range without
 * undefined behavior.
 */

Added helper function that does not call get_random_u32_below()
if proxy_delay is zero and just uses the current value of
jiffies instead, causing pneigh_enqueue() to respond
immediately.

Also added definition of proxy_delay to ip-sysctl.txt since
it was missing.

Signed-off-by: Brian Haley <haleyb.dev@gmail.com>
Link: https://lore.kernel.org/r/20230130171428.367111-1-haleyb.dev@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/networking/ip-sysctl.rst
net/core/neighbour.c

index 39df3cf..87dd1c5 100644 (file)
@@ -1592,6 +1592,14 @@ proxy_arp_pvlan - BOOLEAN
          Hewlett-Packard call it Source-Port filtering or port-isolation.
          Ericsson call it MAC-Forced Forwarding (RFC Draft).
 
+proxy_delay - INTEGER
+       Delay proxy response.
+
+       Delay response to a neighbor solicitation when proxy_arp
+       or proxy_ndp is enabled. A random value between [0, proxy_delay)
+       will be chosen, setting to zero means reply with no delay.
+       Value in jiffies. Defaults to 80.
+
 shared_media - BOOLEAN
        Send(router) or accept(host) RFC1620 shared media redirects.
        Overrides secure_redirects.
index f00a79f..5725811 100644 (file)
@@ -1662,11 +1662,21 @@ static void neigh_proxy_process(struct timer_list *t)
        spin_unlock(&tbl->proxy_queue.lock);
 }
 
+static unsigned long neigh_proxy_delay(struct neigh_parms *p)
+{
+       /* If proxy_delay is zero, do not call get_random_u32_below()
+        * as it is undefined behavior.
+        */
+       unsigned long proxy_delay = NEIGH_VAR(p, PROXY_DELAY);
+
+       return proxy_delay ?
+              jiffies + get_random_u32_below(proxy_delay) : jiffies;
+}
+
 void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
                    struct sk_buff *skb)
 {
-       unsigned long sched_next = jiffies +
-                       get_random_u32_below(NEIGH_VAR(p, PROXY_DELAY));
+       unsigned long sched_next = neigh_proxy_delay(p);
 
        if (p->qlen > NEIGH_VAR(p, PROXY_QLEN)) {
                kfree_skb(skb);