Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?= <bjorn.topel@gmail.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [PATCH net 0/3] Avoid premature Rx buffer reuse for XDP_REDIRECT
Date: Tue, 25 Aug 2020 11:16:26 +0200	[thread overview]
Message-ID: <20200825091629.12949-1-bjorn.topel@gmail.com> (raw)

Intel NICs have a recycle mechanism. The main idea is that a page is
split into two parts. One part is owned by the driver, one part might
be owned by someone else, such as the stack.

The page recycle code, incorrectly, relied on that a page fragment
could not be freed inside xdp_do_redirect(), e.g. a redirect to a
devmap where the ndo_xdp_xmit() implementation would transmit and free
the frame, or xskmap where the frame would be copied to userspace and
freed.

This assumption leads to that page fragments that are used by the
stack/XDP redirect can be reused and overwritten.

To avoid this, store the page count prior invoking
xdp_do_redirect(). The affected drivers are ixgbe, ice, and i40e.

An example how things might go wrong:

t0: Page is allocated, and put on the Rx ring
              +---------------
used by NIC ->| upper buffer
(rx_buffer)   +---------------
              | lower buffer
              +---------------
  page count  == USHRT_MAX
  rx_buffer->pagecnt_bias == USHRT_MAX

t1: Buffer is received, and passed to the stack (e.g.)
              +---------------
              | upper buff (skb)
              +---------------
used by NIC ->| lower buffer
(rx_buffer)   +---------------
  page count  == USHRT_MAX
  rx_buffer->pagecnt_bias == USHRT_MAX - 1

t2: Buffer is received, and redirected
              +---------------
              | upper buff (skb)
              +---------------
used by NIC ->| lower buffer
(rx_buffer)   +---------------

Now, prior calling xdp_do_redirect():
  page count  == USHRT_MAX
  rx_buffer->pagecnt_bias == USHRT_MAX - 2

This means that buffer *cannot* be flipped/reused, because the skb is
still using it.

The problem arises when xdp_do_redirect() actually frees the
segment. Then we get:
  page count  == USHRT_MAX - 1
  rx_buffer->pagecnt_bias == USHRT_MAX - 2

From a recycle perspective, the buffer can be flipped and reused,
which means that the skb data area is passed to the Rx HW ring!

To work around this, the page count is stored prior calling
xdp_do_redirect().

Note that this is not optimal, since the NIC could actually reuse the
"lower buffer" again. However, then we need to track whether
XDP_REDIRECT consumed the buffer or not. This scenario is very rare,
and tracking consumtion status would introduce more complexity.

A big thanks to Li RongQing from Baidu for having patience with me
understanding that there was a bug. I would have given up much
earlier! :-)


Cheers,
Bj?rn

Bj?rn T?pel (3):
  i40e: avoid premature Rx buffer reuse
  ixgbe: avoid premature Rx buffer reuse
  ice: avoid premature Rx buffer reuse

 drivers/net/ethernet/intel/i40e/i40e_txrx.c   | 28 ++++++++++++-----
 drivers/net/ethernet/intel/ice/ice_txrx.c     | 31 +++++++++++++------
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 28 ++++++++++++-----
 3 files changed, 64 insertions(+), 23 deletions(-)


base-commit: 99408c422d336db32bfab5cbebc10038a70cf7d2
-- 
2.25.1


             reply	other threads:[~2020-08-25  9:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-25  9:16 =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?= [this message]
2020-08-25  9:16 ` [Intel-wired-lan] [PATCH net 1/3] i40e: avoid premature Rx buffer reuse =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?=
2020-08-25 11:13   ` Maciej Fijalkowski
2020-08-25 11:25     ` =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?=
2020-08-25 11:29       ` Maciej Fijalkowski
2020-08-25 11:37         ` =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?=
2020-08-25  9:16 ` [Intel-wired-lan] [PATCH net 2/3] ixgbe: " =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?=
2020-08-25  9:55   ` Li, Rongqing
2020-08-25 10:00     ` =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?=
2020-08-25  9:16 ` [Intel-wired-lan] [PATCH net 3/3] ice: " =?unknown-8bit?q?Bj=C3=B6rn_T=C3=B6pel?=
2020-08-25  9:55   ` Li, Rongqing

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200825091629.12949-1-bjorn.topel@gmail.com \
    --to=bjorn.topel@gmail.com \
    --cc=intel-wired-lan@osuosl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox