time_after_eq() only works if the delta is < MAX_ULONG/2.
For a 32bit Dom0, if netfront sends packets at a very low rate, the time
between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2
and the test for timer_after_eq() will be incorrect. Credit will not be
replenished and the guest may become unable to send packets (e.g., if
prior to the long gap, all credit was exhausted).
Use jiffies_64 variant to mitigate this problem for 32bit Dom0.
Suggested-by: Jan Beulich <redacted>
Suggested-by: David Vrabel <redacted>
Signed-off-by: Wei Liu <redacted>
Cc: Ian Campbell <redacted>
Cc: Jason Luan <redacted>
---
drivers/net/xen-netback/common.h | 1 +
drivers/net/xen-netback/interface.c | 4 ++--
drivers/net/xen-netback/netback.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
@@ -1185,18 +1185,17 @@ out:staticbooltx_credit_exceeded(structxenvif*vif,unsignedsize){-unsignedlongnow=jiffies;-unsignedlongnext_credit=-vif->credit_timeout.expires+-msecs_to_jiffies(vif->credit_usec/1000);+u64now=get_jiffies_64();+u64next_credit=vif->credit_window_start++(u64)msecs_to_jiffies(vif->credit_usec/1000);/* Timer could already be pending in rare cases. */if(timer_pending(&vif->credit_timeout))returntrue;/* Passed the point where we can replenish credit? */-if(time_after_eq(now,next_credit)){-vif->credit_timeout.expires=now;+if(time_after_eq64(now,next_credit)){+vif->credit_timeout.expires=(unsignedlong)now;tx_add_credit(vif);}
time_after_eq() only works if the delta is < MAX_ULONG/2.
For a 32bit Dom0, if netfront sends packets at a very low rate, the time
between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2
and the test for timer_after_eq() will be incorrect. Credit will not be
replenished and the guest may become unable to send packets (e.g., if
prior to the long gap, all credit was exhausted).
Use jiffies_64 variant to mitigate this problem for 32bit Dom0.
Suggested-by: Jan Beulich <redacted>
Suggested-by: David Vrabel <redacted>
Signed-off-by: Wei Liu <redacted>
Cc: Ian Campbell <redacted>
Cc: Jason Luan <redacted>
---
drivers/net/xen-netback/common.h | 1 +
drivers/net/xen-netback/interface.c | 4 ++--
drivers/net/xen-netback/netback.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
You simply replace "credit_timeout.expires" with
"vif->credit_window_start" here, and never update
"vif->credit_window_start" in following code.
/* Timer could already be pending in rare cases. */
if (timer_pending(&vif->credit_timeout))
return true;
/* Passed the point where we can replenish credit? */
- if (time_after_eq(now, next_credit)) {
- vif->credit_timeout.expires = now;
+ if (time_after_eq64(now, next_credit)) {
+ vif->credit_timeout.expires = (unsigned long)now;
updates credit_window_start as following,
vif->credit_window_start = (unsigned long)now;
vif->credit_timeout.expires is unsigned long, and this still causes
original issue on 32bit system, which works well on 64bit. Or rewriting
code to avoid uses of vif->credit_timeout.expires, but it is complex.
BTW, I prefer Luan's patch which is simple and clear.
Thanks
Annie
time_after_eq() only works if the delta is < MAX_ULONG/2.
For a 32bit Dom0, if netfront sends packets at a very low rate, the time
between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2
and the test for timer_after_eq() will be incorrect. Credit will not be
replenished and the guest may become unable to send packets (e.g., if
prior to the long gap, all credit was exhausted).
Use jiffies_64 variant to mitigate this problem for 32bit Dom0.
Suggested-by: Jan Beulich <redacted>
Suggested-by: David Vrabel <redacted>
Signed-off-by: Wei Liu <redacted>
Cc: Ian Campbell <redacted>
Cc: Jason Luan <redacted>
---
drivers/net/xen-netback/common.h | 1 +
drivers/net/xen-netback/interface.c | 4 ++--
drivers/net/xen-netback/netback.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/xen-netback/common.h
b/drivers/net/xen-netback/common.h
index 5715318..400fea1 100644
You simply replace "credit_timeout.expires" with
"vif->credit_window_start" here, and never update
"vif->credit_window_start" in following code.
quoted
/* Timer could already be pending in rare cases. */
if (timer_pending(&vif->credit_timeout))
return true;
/* Passed the point where we can replenish credit? */
- if (time_after_eq(now, next_credit)) {
- vif->credit_timeout.expires = now;
+ if (time_after_eq64(now, next_credit)) {
+ vif->credit_timeout.expires = (unsigned long)now;
updates credit_window_start as following,
vif->credit_window_start = (unsigned long)now;
both credit_window_start and credit_timeout.expires need to be updated
here,
vif->credit_window_start = (unsigned long)now;
vif->credit_timeout.expires = (unsigned long)now;
vif->credit_timeout.expires is unsigned long, and this still causes
original issue on 32bit system, which works well on 64bit. Or
rewriting code to avoid uses of vif->credit_timeout.expires, but it is
complex.
My understanding here is wrong, please ignore this.
Thanks
Annie
time_after_eq() only works if the delta is < MAX_ULONG/2.
For a 32bit Dom0, if netfront sends packets at a very low rate, the
time
between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2
and the test for timer_after_eq() will be incorrect. Credit will not be
replenished and the guest may become unable to send packets (e.g., if
prior to the long gap, all credit was exhausted).
Use jiffies_64 variant to mitigate this problem for 32bit Dom0.
Suggested-by: Jan Beulich <redacted>
Suggested-by: David Vrabel <redacted>
Signed-off-by: Wei Liu <redacted>
Cc: Ian Campbell <redacted>
Cc: Jason Luan <redacted>
---
drivers/net/xen-netback/common.h | 1 +
drivers/net/xen-netback/interface.c | 4 ++--
drivers/net/xen-netback/netback.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/xen-netback/common.h
b/drivers/net/xen-netback/common.h
index 5715318..400fea1 100644
You simply replace "credit_timeout.expires" with
"vif->credit_window_start" here, and never update
"vif->credit_window_start" in following code.
quoted
/* Timer could already be pending in rare cases. */
if (timer_pending(&vif->credit_timeout))
return true;
/* Passed the point where we can replenish credit? */
- if (time_after_eq(now, next_credit)) {
- vif->credit_timeout.expires = now;
+ if (time_after_eq64(now, next_credit)) {
+ vif->credit_timeout.expires = (unsigned long)now;
updates credit_window_start as following,
vif->credit_window_start = (unsigned long)now;
both credit_window_start and credit_timeout.expires need to be updated
here,
vif->credit_window_start = (unsigned long)now;
vif->credit_timeout.expires = (unsigned long)now;
Annie should be correct.
It is good to me but i afraid that get_jiffies_64() and
time_after_eq64() will bring some performance's load when transmit is
busy in 32bit. I will do some test about the patch.
No matter what, i prefer own patch.
Thanks,
Jason
vif->credit_timeout.expires is unsigned long, and this still causes
original issue on 32bit system, which works well on 64bit. Or
rewriting code to avoid uses of vif->credit_timeout.expires, but it
is complex.
My understanding here is wrong, please ignore this.
Thanks
Annie
From: David Vrabel <hidden> Date: 2013-10-28 08:21:43
On 27/10/2013 11:11, Wei Liu wrote:
time_after_eq() only works if the delta is < MAX_ULONG/2.
For a 32bit Dom0, if netfront sends packets at a very low rate, the time
between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2
and the test for timer_after_eq() will be incorrect. Credit will not be
replenished and the guest may become unable to send packets (e.g., if
prior to the long gap, all credit was exhausted).
Use jiffies_64 variant to mitigate this problem for 32bit Dom0.
Thanks.
Suggested-by: Jan Beulich <redacted>
Suggested-by: David Vrabel <redacted>
@@ -1185,18 +1185,17 @@ out:staticbooltx_credit_exceeded(structxenvif*vif,unsignedsize){-unsignedlongnow=jiffies;-unsignedlongnext_credit=-vif->credit_timeout.expires+-msecs_to_jiffies(vif->credit_usec/1000);+u64now=get_jiffies_64();+u64next_credit=vif->credit_window_start++(u64)msecs_to_jiffies(vif->credit_usec/1000);/* Timer could already be pending in rare cases. */if(timer_pending(&vif->credit_timeout))returntrue;/* Passed the point where we can replenish credit? */-if(time_after_eq(now,next_credit)){-vif->credit_timeout.expires=now;+if(time_after_eq64(now,next_credit)){+vif->credit_timeout.expires=(unsignedlong)now;
Need to set vif->credit_window_start = now here instead of .expires.
time_after_eq() only works if the delta is < MAX_ULONG/2.
For a 32bit Dom0, if netfront sends packets at a very low rate, the time
between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2
and the test for timer_after_eq() will be incorrect. Credit will not be
replenished and the guest may become unable to send packets (e.g., if
prior to the long gap, all credit was exhausted).
Use jiffies_64 variant to mitigate this problem for 32bit Dom0.
Thanks.
quoted
Suggested-by: Jan Beulich <redacted>
Suggested-by: David Vrabel <redacted>
@@ -1185,18 +1185,17 @@ out:staticbooltx_credit_exceeded(structxenvif*vif,unsignedsize){-unsignedlongnow=jiffies;-unsignedlongnext_credit=-vif->credit_timeout.expires+-msecs_to_jiffies(vif->credit_usec/1000);+u64now=get_jiffies_64();+u64next_credit=vif->credit_window_start++(u64)msecs_to_jiffies(vif->credit_usec/1000);/* Timer could already be pending in rare cases. */if(timer_pending(&vif->credit_timeout))returntrue;/* Passed the point where we can replenish credit? */-if(time_after_eq(now,next_credit)){-vif->credit_timeout.expires=now;+if(time_after_eq64(now,next_credit)){+vif->credit_timeout.expires=(unsignedlong)now;
Need to set vif->credit_window_start = now here instead of .expires.
I agree Annie's suggest. add the below line;
vif->credit_window_start = now
vif->credit_timeout.expires = (unsigned long)now;
On Mon, Oct 28, 2013 at 10:58:32AM +0800, annie li wrote:
[...]
quoted
quoted
if (timer_pending(&vif->credit_timeout))
return true;
/* Passed the point where we can replenish credit? */
- if (time_after_eq(now, next_credit)) {
- vif->credit_timeout.expires = now;
+ if (time_after_eq64(now, next_credit)) {
+ vif->credit_timeout.expires = (unsigned long)now;
updates credit_window_start as following,
vif->credit_window_start = (unsigned long)now;
both credit_window_start and credit_timeout.expires need to be
updated here,
vif->credit_window_start = (unsigned long)now;
vif->credit_timeout.expires = (unsigned long)now;
IMHO we don't need to update .expires anymore -- we now track the window
with another variable.
Wei.