Jason Wang <jasow...@redhat.com> writes:

> On 2019/4/10 下午9:01, David Woodhouse wrote:
>> On Wed, 2019-04-10 at 15:01 +0300, David Woodhouse wrote:
>>> --- a/drivers/net/tun.c
>>> +++ b/drivers/net/tun.c
>>> @@ -1125,7 +1128,9 @@ static netdev_tx_t tun_net_xmit(struct sk_buff
>>> *skb, struct net_device *dev)
>>>          if (tfile->flags & TUN_FASYNC)
>>>                  kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
>>>          tfile->socket.sk->sk_data_ready(tfile->socket.sk);
>>>   
>>> +       if (!ptr_ring_empty(&tfile->tx_ring))
>>> +               netif_stop_queue(tun->dev);
>>>          rcu_read_unlock();
>>>          return NETDEV_TX_OK;
>>>   
>>>
>> Hm, that should be using ptr_ring_full() shouldn't it? So...
>>
>> --- a/drivers/net/tun.c
>> +++ b/drivers/net/tun.c
>> @@ -1121,6 +1121,9 @@ static netdev_tx_t tun_net_xmit(struct s
>>      if (ptr_ring_produce(&tfile->tx_ring, skb))
>>              goto drop;
>>   
>> +    if (ptr_ring_full(&tfile->tx_ring))
>> +            netif_stop_queue(tun->dev);
>> +
>>      /* Notify and wake up reader process */
>>      if (tfile->flags & TUN_FASYNC)
>>              kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
>> @@ -2229,6 +2232,7 @@ static ssize_t tun_do_read(struct tun_st
>>                      consume_skb(skb);
>>      }
>>   
>> +    netif_wake_queue(tun->dev);
>>      return ret;
>>   }
>>   
>>
>> That doesn't seem to make much difference at all; it's still dropping a
>> lot of packets because ptr_ring_produce() is returning non-zero.
>
>
> I think you need try to stop the queue just in this case? Ideally we may 
> want to stop the queue when the queue is about to full, but we don't 
> have such helper currently.

Ideally we want to react when the queue starts building rather than when
it starts getting full; by pushing back on upper layers (or, if
forwarding, dropping packets to signal congestion).

In practice, this means tuning the TX ring to the *minimum* size it can
be without starving (this is basically what BQL does for Ethernet), and
keeping packets queued in the qdisc layer instead, where it can be
managed...

-Toke

Reply via email to