Re: UDP multicast packet loss not reported if TX ring overrun?
From: Eric Dumazet <hidden>
Date: 2009-08-24 22:02:57
Subsystem:
networking [general], networking [ipv4/ipv6], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds
Christoph Lameter a écrit :
quoted hunk ↗ jump to hunk
On Mon, 17 Aug 2009, Sridhar Samudrala wrote:quoted
So it is possible that there is some other place in the stack where the packets are gettting dropped but not counted.Such a deed occurs in ip_push_pending_frames(): /* Netfilter gets whole the not fragmented skb. */ err = ip_local_out(skb); if (err) { if (err > 0) err = inet->recverr ? net_xmit_errno(err) : 0; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ if (err) goto error; } out: ip_cork_release(inet); return err; error: IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); goto out; So if ip_local_out returns NET_XMIT_DROP then its simply going to be replaced by 0. Then we check err again and there is no error!!!! The statistics are only generated if IP_RECVERR is set. Could we move the increment of IPSTATS_MIB_OUTDISCARDS up so that it is incremented regardless of the setting of IP_RECVERR? F.e? Subject: Report TX drops Incrementing of TX drop counters currently does not work if errors from the network stack are suppressed (IP_RECVERR off). Increment the statistics independently of the setting of IP_RECVERR. Signed-off-by: Christoph Lameter <redacted> --- net/ipv4/ip_output.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) Index: linux-2.6/net/ipv4/ip_output.c ===================================================================--- linux-2.6.orig/net/ipv4/ip_output.c 2009-08-24 17:04:27.000000000 +0000 +++ linux-2.6/net/ipv4/ip_output.c 2009-08-24 17:32:05.000000000 +0000@@ -1300,20 +1300,21 @@ int ip_push_pending_frames(struct sock * /* Netfilter gets whole the not fragmented skb. */ err = ip_local_out(skb); - if (err) { - if (err > 0) - err = inet->recverr ? net_xmit_errno(err) : 0; - if (err) - goto error; + if (err > 0) { + /* The packet was dropped by the network subsystem */ + IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); + + /* + * Errors are not passed on if the socket + * does not process errors (see IP_RECVERR). + * net_xmit_errno filters NET_XMIT_CN. + */ + err = inet->recverr ? net_xmit_errno(err) : 0; } out: ip_cork_release(inet); return err; - -error: - IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); - goto out; } /*
NET_XMIT_CN strikes again :) Well, if ip_local_out() returns a negative error (say -EPERM for example), your patch disables OUTDISCARDS increments. Maybe a simpler patch like this one ? [PATCH] net: correctly updates OUTDISCARDS in ip_push_pending_frames() ip_push_pending_frames() can fail to send a frame because of a congestioned device. In this case, we increment SNMP OUTDISCARDS only if user set IP_RECVERR, which is not RFC conformant. Only case where we should not update OUTDISCARDS is when ip_local_output() return value is NET_XMIT_CN (meaning skb was xmitted but future frames might be dropped) Signed-off-by: Christoph Lameter <redacted> Signed-off-by: Eric Dumazet <redacted> ---
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 7d08210..27a5b79 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c@@ -1301,19 +1301,15 @@ int ip_push_pending_frames(struct sock *sk) /* Netfilter gets whole the not fragmented skb. */ err = ip_local_out(skb); if (err) { + if (err != NET_XMIT_CN) + IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); if (err > 0) err = inet->recverr ? net_xmit_errno(err) : 0; - if (err) - goto error; } out: ip_cork_release(inet); return err; - -error: - IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); - goto out; } /*