| From foo@baz Mon Dec 20 02:55:54 PM CET 2021 |
| From: Juergen Gross <jgross@suse.com> |
| Date: Tue, 30 Nov 2021 08:36:12 +0100 |
| Subject: xen/netback: don't queue unlimited number of packages |
| |
| From: Juergen Gross <jgross@suse.com> |
| |
| commit be81992f9086b230623ae3ebbc85ecee4d00a3d3 upstream. |
| |
| In case a guest isn't consuming incoming network traffic as fast as it |
| is coming in, xen-netback is buffering network packages in unlimited |
| numbers today. This can result in host OOM situations. |
| |
| Commit f48da8b14d04ca8 ("xen-netback: fix unlimited guest Rx internal |
| queue and carrier flapping") meant to introduce a mechanism to limit |
| the amount of buffered data by stopping the Tx queue when reaching the |
| data limit, but this doesn't work for cases like UDP. |
| |
| When hitting the limit don't queue further SKBs, but drop them instead. |
| In order to be able to tell Rx packages have been dropped increment the |
| rx_dropped statistics counter in this case. |
| |
| It should be noted that the old solution to continue queueing SKBs had |
| the additional problem of an overflow of the 32-bit rx_queue_len value |
| would result in intermittent Tx queue enabling. |
| |
| This is part of XSA-392 |
| |
| Fixes: f48da8b14d04ca8 ("xen-netback: fix unlimited guest Rx internal queue and carrier flapping") |
| Signed-off-by: Juergen Gross <jgross@suse.com> |
| Reviewed-by: Jan Beulich <jbeulich@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/xen-netback/rx.c | 18 +++++++++++------- |
| 1 file changed, 11 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/net/xen-netback/rx.c |
| +++ b/drivers/net/xen-netback/rx.c |
| @@ -88,16 +88,19 @@ void xenvif_rx_queue_tail(struct xenvif_ |
| |
| spin_lock_irqsave(&queue->rx_queue.lock, flags); |
| |
| - if (skb_queue_empty(&queue->rx_queue)) |
| - xenvif_update_needed_slots(queue, skb); |
| - |
| - __skb_queue_tail(&queue->rx_queue, skb); |
| - |
| - queue->rx_queue_len += skb->len; |
| - if (queue->rx_queue_len > queue->rx_queue_max) { |
| + if (queue->rx_queue_len >= queue->rx_queue_max) { |
| struct net_device *dev = queue->vif->dev; |
| |
| netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id)); |
| + kfree_skb(skb); |
| + queue->vif->dev->stats.rx_dropped++; |
| + } else { |
| + if (skb_queue_empty(&queue->rx_queue)) |
| + xenvif_update_needed_slots(queue, skb); |
| + |
| + __skb_queue_tail(&queue->rx_queue, skb); |
| + |
| + queue->rx_queue_len += skb->len; |
| } |
| |
| spin_unlock_irqrestore(&queue->rx_queue.lock, flags); |
| @@ -147,6 +150,7 @@ static void xenvif_rx_queue_drop_expired |
| break; |
| xenvif_rx_dequeue(queue); |
| kfree_skb(skb); |
| + queue->vif->dev->stats.rx_dropped++; |
| } |
| } |
| |