Fix BUG of ip_rt_send_redirect()
Subsystems (3)
PATCH 1/1 Fix BUG of ip_rt_send_redirect()
[1]Summary of the problem:
On IA32 system, If jiffies - b > 0x7fffffff, router can not send redirect packet.unsigned long b = rt->u.dst.rate_last +(ip_rt_redirect_load << rt->u.dst.rate_tokens)
[2]Full description of the problem:
In linux kernel, if time_after(jiffies, (rt->u.dst.rate_last +(ip_rt_redirect_load << rt->u.dst.rate_tokens)) == false, router will not send redirect packet. Here define b = rt-
Quoted 1 line
u.dst.rate_last +(ip_rt_redirect_load <<
rt->u.dst.rate_tokens):
1. If (jiffies - b <= 0x7fffffff), time_after(jiffies, b) == true, router will send redirect packet.
2. If (jiffies - b > 0x7fffffff), time_after(jiffies, b) == false, router will not send redirect packet. For example: when I add a router after system boot, jiffies = (unsigned long)(-300000), rt->u.dst.rate_last = 0, rt->u.dst.rate_tokens = 0, b = 20, time_after((unsigned long)(-300000), 20) == false, send redirect packet can not be send even if router is used in the first time.
When router send a redirect packet in time b, and before jiffies increased to 0x7fffffff + b, router can send redirect packet. But if a redirect packet must be send in 0x80000000+ b, time_after(jiffies, b) == false, redirect packet will not be send also. So between time (0x80000000+ b) to time b, router do not send redirect packet. That is to say, in a circle of jiffies, router has 24.9 days can not send redirect packet (0x80000000/1000/60/60/24=24.9).
jiffies b
------|------------------------------|----------------------|---->time
0x80000000+b b 0x7fffffff+b
|<--jiffies - b < 0x7fffffff-->|Following is my patch.
net/ipv4/route.c renamed from net/ipv4/route.c.org +4 -2
@@ -1196,7 +1196,8 @@ void ip_rt_send_redirect(struct sk_buff/* No redirected packets during ip_rt_redirect_silence; * reset the algorithm. */ - if (time_after(jiffies, rt->u.dst.rate_last + ip_rt_redirect_silence) +if (time_after (jiffies, rt->u.dst.rate_last + ip_rt_redirect_silence) || +time_after (rt->u.dst.rate_last, jiffies)) rt->u.dst.rate_tokens =0 ;/* Too many ignored redirects; do not send anything
@@ -1212,7 +1213,8 @@ void ip_rt_send_redirect(struct sk_buff*/ if (time_after (jiffies, (rt->u.dst.rate_last + - (ip_rt_redirect_load << rt->u.dst.rate_tokens)))) { + (ip_rt_redirect_load << rt->u.dst.rate_tokens))) || +time_after (rt->u.dst.rate_last, jiffies)) {icmp_send (skb,ICMP_REDIRECT ,ICMP_REDIR_HOST , rt->rt_gateway); rt->u.dst.rate_last = jiffies; ++rt->u.dst.rate_tokens;
Quoted 54 lines · On Thu, 16 Nov 2006 23:57:50 -0500 Li Yewang <[email protected]> wrote:
[1]Summary of the problem:
On IA32 system, If jiffies - b >0x7fffffff, router can not send redirect packet.unsigned long b =rt->u.dst.rate_last+(ip_rt_redirect_load <<rt->u.dst.rate_tokens)[2]Full description of the problem:
In linux kernel, if time_after(jiffies, (rt->u.dst.rate_last+(ip_rt_redirect_load <<rt->u.dst.rate_tokens)) == false, router will not send redirect packet. Here define b = rt-Quoted 1 line
u.dst.rate_last +(ip_rt_redirect_load <<
rt->u.dst.rate_tokens):1. If (jiffies - b <=
0x7fffffff),time_after(jiffies, b)== true, router will send redirect packet.2. If (jiffies - b >
0x7fffffff),time_after(jiffies, b)== false, router will not send redirect packet. For example: when I add a router after system boot, jiffies = (unsigned long)(-300000),rt->u.dst.rate_last= 0,rt->u.dst.rate_tokens= 0, b = 20,time_after((unsigned long)(-300000), 20)== false, send redirect packet can not be send even if router is used in the first time.When router send a redirect packet in time b, and before jiffies increased to
0x7fffffff+ b, router can send redirect packet. But if a redirect packet must be send in 0x80000000+ b,time_after(jiffies, b)== false, redirect packet will not be send also. So between time (0x80000000+ b) to time b, router do not send redirect packet. That is to say, in a circle of jiffies, router has 24.9 days can not send redirect packet (0x80000000/1000/60/60/24=24.9).jiffies b
------|------------------------------|----------------------|---->time 0x80000000+b b 0x7fffffff+b |<--jiffies - b < 0x7fffffff-->|Following is my patch.
Signed-off-by Li Yewang <[email protected]>net/ipv4/route.c renamed from net/ipv4/route.c.org +2
-1@@ -1196,7 +1196,8 @@ void ip_rt_send_redirect(struct sk_buff/* No redirected packets during ip_rt_redirect_silence; * reset the algorithm. */ - if (time_after(jiffies, rt->u.dst.rate_last + ip_rt_redirect_silence) +if (time_after (jiffies, rt->u.dst.rate_last + ip_rt_redirect_silence) || +time_after (rt->u.dst.rate_last, jiffies)) rt->u.dst.rate_tokens =0 ;/* Too many ignored redirects; do not send anything
net/ipv4/route.c void ip_rt_send_redirect(struct sk_buff · line 1220
Quoted 9 lines
net/ipv4/route.c renamed from net/ipv4/route.c.org +2
-1@@ -1212,7 +1213,8 @@ void ip_rt_send_redirect(struct sk_buff*/ if (time_after (jiffies, (rt->u.dst.rate_last + - (ip_rt_redirect_load << rt->u.dst.rate_tokens)))) { + (ip_rt_redirect_load << rt->u.dst.rate_tokens))) || +time_after (rt->u.dst.rate_last, jiffies)) {icmp_send (skb,ICMP_REDIRECT ,ICMP_REDIR_HOST , rt->rt_gateway); rt->u.dst.rate_last = jiffies; ++rt->u.dst.rate_tokens;
Wouldn't making ip_rt_redirect_load and other unsigned long instead of int fix the problem?
Remember time_after() works correctly for values that wraparound.
Quoted 32 lines · Stephen Hemminger
Quoted 21 lines · On Thu, 16 Nov 2006 23:57:50 -0500 Li Yewang <[email protected]> wrote:
[1]Summary of the problem:
On IA32 system, If jiffies - b >0x7fffffff, router can not send redirect packet.unsigned long b =rt->u.dst.rate_last+(ip_rt_redirect_load <<rt->u.dst.rate_tokens)[2]Full description of the problem:
In linux kernel, if time_after(jiffies, (rt->u.dst.rate_last+(ip_rt_redirect_load <<rt->u.dst.rate_tokens)) == false, router will not send redirect packet. Here define b = rt-Quoted 1 line
u.dst.rate_last +(ip_rt_redirect_load <<
rt->u.dst.rate_tokens):1. If (jiffies - b <=
0x7fffffff),time_after(jiffies, b)== true, router will send redirect packet.2. If (jiffies - b >
0x7fffffff),time_after(jiffies, b)== false, router will not send redirect packet. For example: when I add a router after system boot, jiffies = (unsigned long)(-300000),rt->u.dst.rate_last= 0,rt->u.dst.rate_tokens= 0, b = 20,time_after((unsigned long)(-300000), 20)== false, send redirect packet can not be send even if router is used in the first time.Quoted 7 lines
When router send a redirect packet in time b, and before jiffies increased to
0x7fffffff+ b, router can send redirect packet. But if a redirect packet must be send in 0x80000000+ b,time_after(jiffies, b)== false, redirect packet will not be send also. So between time (0x80000000+ b) to time b, router do not send redirect packet. That is to say, in a circle of jiffies, router has 24.9 days can not send redirect packet (0x80000000/1000/60/60/24=24.9).
Quoted 3 lines
Wouldn't making
ip_rt_redirect_loadand other unsigned long instead of int fix the problem?Remember
time_after()works correctly for values that wraparound.
Yes, time_after() works correctly for values that wraparound. For examples: if time a = (unsigned long)(-1), and time b = 1; time_after(b, a) = true. But if a is increaseing, after a circle of jiffies, a' = a + (unsigned long)(-1) + 1 = (unsigned long)(-1) = a,
this time a' is after b, but time_after(b, a') still equal to true,because values that wraparound can not be making in time_after().
Regards
Quoted 7 lines · Wei Yongjun
Yes,
time_after()works correctly for values that wraparound. For examples: if time a = (unsigned long)(-1), and time b = 1;time_after(b, a)= true. But if a is increaseing, after a circle of jiffies, a' = a + (unsigned long)(-1)
+ 1 = (unsigned long)(-1) = a,
this time a' is after b, buttime_after(b, a')still equal to true,because values that wraparound can not be making intime_after().
I think there are two problems here:
1) The first time we hit the check rate_last is zero. We should simply proceed with the redirect rather than treating this as a jiffies value.
2) When a dst is so old that the jiffies have wrapped around. I'm not sure whether this is worth solving as it should be extremely rare unless your HZ is sufficiently large and you're on a 32-bit platform.
One solution would be to periodically reset the rate_last fields to their original states. Perhaps we can combine that with the GC.
Cheers,
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtYes, the first time when router want to send redirect packet, We should send the redirect packet simply and do not regard the jiffies. But the kernel has bugs as follow:
1.The kernel can not send the redirect packet at the begin 5 minutes
when the system boot(32bit machine).
2.In a circle of jiffies, router has 24.9 days can not send redirect packet.
I think my patch can solve the bugs.
Quoted 23 lines · Herbert Xu
I think there are two problems here:
1) The first time we hit the check
rate_lastis zero. We should simply proceed with the redirect rather than treating this as a jiffies value.2) When a dst is so old that the jiffies have wrapped around. I'm not sure whether this is worth solving as it should be extremely rare unless your HZ is sufficiently large and you're on a 32-bit platform.
One solution would be to periodically reset the
rate_lastfields to their original states. Perhaps we can combine that with the GC.Cheers,
Signature · 8 lines
Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt - 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
Quoted 5 lines · Herbert Xu [email protected] wrote:
I think there are two problems here:
1) The first time we hit the check
rate_lastis zero. We should simply proceed with the redirect rather than treating this as a jiffies value.
Quoted 8 lines
2) When a dst is so old that the jiffies have wrapped around. I'm not sure whether this is worth solving as it should be extremely rare unless your HZ is sufficiently large and you're on a 32-bit platform.
One solution would be to periodically reset the
rate_lastfields to their original states. Perhaps we can combine that with the GC.Cheers,
Mr Herbert Xu
Sorry for later reply
I have some questions about your advice:
1) If the first time when we send the redirect packets, but the time_after(jiffies, b)==false. So the redirect packets can not be sended.
This situation happens when the system of 32-bit boot on less than 5 minutes. This must be the kernel bug.
2) If the router used frequently, the garbage collect function can not free this dst. Next time when we want this router to send redirect packets, and if the jiffies wraparound and time_after(jiffies,b)==false, the redirect packets can not be sended. So we must consider this situation and solve this problem.
Quoted 9 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
-
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