Commit 19e16d22 authored by Hangbin Liu's avatar Hangbin Liu Committed by David S. Miller
Browse files

neigh: support smaller retrans_time settting



Currently, we limited the retrans_time to be greater than HZ/2. i.e.
setting retrans_time less than 500ms will not work. This makes the user
unable to achieve a more accurate control for bonding arp fast failover.

Update the sanity check to HZ/100, which is 10ms, to let users have more
ability on the retrans_time control.

v3: sync the behavior with IPv6 and update all the timer handler
v2: use HZ instead of hard code number

Signed-off-by: default avatarHangbin Liu <liuhangbin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 64948427
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -1065,11 +1065,12 @@ static void neigh_timer_handler(struct timer_list *t)
			neigh->updated = jiffies;
			atomic_set(&neigh->probes, 0);
			notify = 1;
			next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
			next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
					 HZ/100);
		}
	} else {
		/* NUD_PROBE|NUD_INCOMPLETE */
		next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
		next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME), HZ/100);
	}

	if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
@@ -1125,7 +1126,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
			neigh->nud_state     = NUD_INCOMPLETE;
			neigh->updated = now;
			next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
					 HZ/2);
					 HZ/100);
			neigh_add_timer(neigh, next);
			immediate_probe = true;
		} else {
@@ -1427,7 +1428,8 @@ void __neigh_set_probe_once(struct neighbour *neigh)
	neigh->nud_state = NUD_INCOMPLETE;
	atomic_set(&neigh->probes, neigh_max_probes(neigh));
	neigh_add_timer(neigh,
			jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
			jiffies + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
				      HZ/100));
}
EXPORT_SYMBOL(__neigh_set_probe_once);

+4 −3
Original line number Diff line number Diff line
@@ -1357,7 +1357,7 @@ retry:

	regen_advance = idev->cnf.regen_max_retry *
			idev->cnf.dad_transmits *
			NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
			max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;

	/* recalculate max_desync_factor each time and update
	 * idev->desync_factor if it's larger
@@ -4121,7 +4121,8 @@ static void addrconf_dad_work(struct work_struct *w)

	ifp->dad_probes--;
	addrconf_mod_dad_work(ifp,
			      NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
			      max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME),
				  HZ/100));
	spin_unlock(&ifp->lock);
	write_unlock_bh(&idev->lock);

@@ -4527,7 +4528,7 @@ restart:
				   !(ifp->flags&IFA_F_TENTATIVE)) {
				unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
					ifp->idev->cnf.dad_transmits *
					NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME) / HZ;
					max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;

				if (age >= ifp->prefered_lft - regen_advance) {
					struct inet6_ifaddr *ifpub = ifp->ifpub;
+2 −2
Original line number Diff line number Diff line
@@ -1359,8 +1359,8 @@ skip_defrtr:

		if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
			rtime = (rtime*HZ)/1000;
			if (rtime < HZ/10)
				rtime = HZ/10;
			if (rtime < HZ/100)
				rtime = HZ/100;
			NEIGH_VAR_SET(in6_dev->nd_parms, RETRANS_TIME, rtime);
			in6_dev->tstamp = jiffies;
			send_ifinfo_notify = true;