Message ID | 4A9EF113.9030102@gmail.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
From: Eric Dumazet <eric.dumazet@gmail.com> Date: Thu, 03 Sep 2009 00:26:27 +0200 > Here is an updated version of the patch, after Christoph comments. > > > > [PATCH net-next-2.6] ip: Report qdisc packet drops Looks great, applied! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Christoph Lameter a écrit : > On Thu, 3 Sep 2009, Eric Dumazet wrote: >> index 29ebb0d..ebaaa7f 100644 >> --- a/net/ipv4/udp.c >> +++ b/net/ipv4/udp.c >> @@ -561,12 +561,18 @@ static int udp_push_pending_frames(struct sock *sk) >> >> send: >> err = ip_push_pending_frames(sk); >> + if (err) { >> + if (err == -ENOBUFS && !inet->recverr) { >> + UDP_INC_STATS_USER(sock_net(sk), >> + UDP_MIB_SNDBUFERRORS, is_udplite); > > This means that we now do not increment SNDBUFERRORS if IP_RECVERR is set. > > I think it would be better to move UDP_INC_STATS_USER before the if > statement. That will also simplify the code further. > > I believe you already said this once Christoph on a previous patch, and I replied that in case of IP_RECVERR set, udp_push_pending_frames() returns -ENOBUFS to its caller : udp_sendmsg() And the caller takes care of : out: ip_rt_put(rt); if (free) kfree(ipc.opt); if (!err) return len; /* * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting * ENOBUFS might not be good (it's not tunable per se), but otherwise * we don't have a good statistic (IpOutDiscards but it can be too many * things). We could add another new stat but at least for now that * seems like overkill. */ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_SNDBUFERRORS, is_udplite); } return err; -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 3 Sep 2009, Eric Dumazet wrote: > index 29ebb0d..ebaaa7f 100644 > --- a/net/ipv4/udp.c > +++ b/net/ipv4/udp.c > @@ -561,12 +561,18 @@ static int udp_push_pending_frames(struct sock *sk) > > send: > err = ip_push_pending_frames(sk); > + if (err) { > + if (err == -ENOBUFS && !inet->recverr) { > + UDP_INC_STATS_USER(sock_net(sk), > + UDP_MIB_SNDBUFERRORS, is_udplite); This means that we now do not increment SNDBUFERRORS if IP_RECVERR is set. I think it would be better to move UDP_INC_STATS_USER before the if statement. That will also simplify the code further. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 3 Sep 2009, Eric Dumazet wrote: > >> --- a/net/ipv4/udp.c > >> +++ b/net/ipv4/udp.c > >> @@ -561,12 +561,18 @@ static int udp_push_pending_frames(struct sock *sk) > >> > >> send: > >> err = ip_push_pending_frames(sk); > >> + if (err) { > >> + if (err == -ENOBUFS && !inet->recverr) { > >> + UDP_INC_STATS_USER(sock_net(sk), > >> + UDP_MIB_SNDBUFERRORS, is_udplite); > > > > This means that we now do not increment SNDBUFERRORS if IP_RECVERR is set. > > > > I think it would be better to move UDP_INC_STATS_USER before the if > > statement. That will also simplify the code further. > > > > > > I believe you already said this once Christoph on a previous patch, and I > replied that in case of IP_RECVERR set, udp_push_pending_frames() > returns -ENOBUFS to its caller : udp_sendmsg() Ahhh. I see. Would it not be better to have a single location where the SNDBUFERRORS are accounted for? Check for -ENOBUFS before the code in udp_sendmsg()? Hmmm.. The control flow is a bit complicated there... -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 7d08210..afae0cb 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1302,7 +1302,7 @@ int ip_push_pending_frames(struct sock *sk) err = ip_local_out(skb); if (err) { if (err > 0) - err = inet->recverr ? net_xmit_errno(err) : 0; + err = net_xmit_errno(err); if (err) goto error; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2979f14..ebb1e58 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -375,7 +375,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, err = NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) - err = inet->recverr ? net_xmit_errno(err) : 0; + err = net_xmit_errno(err); if (err) goto error; out: @@ -386,6 +386,8 @@ error_fault: kfree_skb(skb); error: IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); + if (err == -ENOBUFS && !inet->recverr) + err = 0; return err; } @@ -576,8 +578,11 @@ back_from_confirm: &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); - else if (!(msg->msg_flags & MSG_MORE)) + else if (!(msg->msg_flags & MSG_MORE)) { err = ip_push_pending_frames(sk); + if (err == -ENOBUFS && !inet->recverr) + err = 0; + } release_sock(sk); } done: diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 29ebb0d..ebaaa7f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -561,12 +561,18 @@ static int udp_push_pending_frames(struct sock *sk) send: err = ip_push_pending_frames(sk); + if (err) { + if (err == -ENOBUFS && !inet->recverr) { + UDP_INC_STATS_USER(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); + err = 0; + } + } else + UDP_INC_STATS_USER(sock_net(sk), + UDP_MIB_OUTDATAGRAMS, is_udplite); out: up->len = 0; up->pending = 0; - if (!err) - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_OUTDATAGRAMS, is_udplite); return err; } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index a931229..cd48801 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1511,7 +1511,7 @@ int ip6_push_pending_frames(struct sock *sk) err = ip6_local_out(skb); if (err) { if (err > 0) - err = np->recverr ? net_xmit_errno(err) : 0; + err = net_xmit_errno(err); if (err) goto error; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5068410..7d675b8 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -642,7 +642,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) - err = np->recverr ? net_xmit_errno(err) : 0; + err = net_xmit_errno(err); if (err) goto error; out: @@ -653,6 +653,8 @@ error_fault: kfree_skb(skb); error: IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); + if (err == -ENOBUFS && !np->recverr) + err = 0; return err; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 20d2ffc..1640406 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -724,12 +724,18 @@ static int udp_v6_push_pending_frames(struct sock *sk) send: err = ip6_push_pending_frames(sk); + if (err) { + if (err == -ENOBUFS && !inet6_sk(sk)->recverr) { + UDP6_INC_STATS_USER(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); + err = 0; + } + } else + UDP6_INC_STATS_USER(sock_net(sk), + UDP_MIB_OUTDATAGRAMS, is_udplite); out: up->len = 0; up->pending = 0; - if (!err) - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_OUTDATAGRAMS, is_udplite); return err; }