Commit 22069735 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'eth-fbnic-fix-and-improve-header-data-split-configuration'



Bobby Eshleman says:

====================
eth: fbnic: fix and improve header/data split configuration

This series fixes TCP HDS configuration in the fbnic driver and adds a
devmem selftest for the intended behavior.

The issues fixed include setting the correct CSR for EN_HDR_SPLIT,
adjusting the hds threshold clamp to avoid long headers overflowing into
the payload page, and configuring the device to use L4/L3/L2 header
boundaries when present by programming the DMA hint bit unconditionally
for all steering rule types.

Prior to these fixes, small payloads fail devmem.check_rx_hds().

Testing:

IFC0=enp1s0
IFC1=eth0

export REMOTE_TYPE=netns
export REMOTE_ARGS=ns-remote
export NETIF=$IFC0
export LOCAL_V4=192.0.3.1
export REMOTE_V4=192.0.3.2
sysctl -w net.ipv6.conf.$IFC0.keep_addr_on_down=1

./tools/testing/selftests/drivers/net/hw/devmem.py

TAP version 13
1..4
ok 1 devmem.check_rx
ok 2 devmem.check_tx
ok 3 devmem.check_tx_chunks
ok 4 devmem.check_rx_hds

To: Alexander Duyck <alexanderduyck@fb.com>
To: Jakub Kicinski <kuba@kernel.org>
To: kernel-team@meta.com
To: Andrew Lunn <andrew+netdev@lunn.ch>
To: David S. Miller <davem@davemloft.net>
To: Eric Dumazet <edumazet@google.com>
To: Paolo Abeni <pabeni@redhat.com>
To: Mohsin Bashir <mohsin.bashr@gmail.com>
To: Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org

Signed-off-by: default avatarBobby Eshleman <bobbyeshleman@meta.com>
====================

Link: https://patch.msgid.link/20260211-fbnic-tcp-hds-fixes-v1-0-55d050e6f606@meta.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents ee5492fd e7a3c1ad
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1145,6 +1145,9 @@ static int fbnic_set_cls_rule_ins(struct fbnic_net *fbn,
		return -EINVAL;
	}

	dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT,
			   FBNIC_RCD_HDR_AL_DMA_HINT_L4);

	/* Write action table values */
	act_tcam->dest = dest;
	act_tcam->rss_en_mask = fbnic_flow_hash_2_rss_en_mask(fbn, hash_idx);
+2 −3
Original line number Diff line number Diff line
@@ -338,7 +338,6 @@ void fbnic_rss_reinit(struct fbnic_dev *fbd, struct fbnic_net *fbn)
		else if (tstamp_mask & (1u << flow_type))
			dest |= FBNIC_RPC_ACT_TBL0_TS_ENA;

		if (act1_value[flow_type] & FBNIC_RPC_TCAM_ACT1_L4_VALID)
		dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT,
				   FBNIC_RCD_HDR_AL_DMA_HINT_L4);

+14 −11
Original line number Diff line number Diff line
@@ -2591,7 +2591,8 @@ static void fbnic_enable_bdq(struct fbnic_ring *hpq, struct fbnic_ring *ppq)
}

static void fbnic_config_drop_mode_rcq(struct fbnic_napi_vector *nv,
				       struct fbnic_ring *rcq, bool tx_pause)
				       struct fbnic_ring *rcq, bool tx_pause,
				       bool hdr_split)
{
	struct fbnic_net *fbn = netdev_priv(nv->napi.dev);
	u32 drop_mode, rcq_ctl;
@@ -2604,22 +2605,26 @@ static void fbnic_config_drop_mode_rcq(struct fbnic_napi_vector *nv,
	/* Specify packet layout */
	rcq_ctl = FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_DROP_MODE_MASK, drop_mode) |
	    FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_HROOM_MASK, FBNIC_RX_HROOM) |
	    FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK, FBNIC_RX_TROOM);
	    FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK, FBNIC_RX_TROOM) |
	    FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT, hdr_split);

	fbnic_ring_wr32(rcq, FBNIC_QUEUE_RDE_CTL0, rcq_ctl);
}

void fbnic_config_drop_mode(struct fbnic_net *fbn, bool tx_pause)
void fbnic_config_drop_mode(struct fbnic_net *fbn, bool txp)
{
	bool hds;
	int i, t;

	hds = fbn->hds_thresh < FBNIC_HDR_BYTES_MIN;

	for (i = 0; i < fbn->num_napi; i++) {
		struct fbnic_napi_vector *nv = fbn->napi[i];

		for (t = 0; t < nv->rxt_count; t++) {
			struct fbnic_q_triad *qt = &nv->qt[nv->txt_count + t];

			fbnic_config_drop_mode_rcq(nv, &qt->cmpl, tx_pause);
			fbnic_config_drop_mode_rcq(nv, &qt->cmpl, txp, hds);
		}
	}
}
@@ -2670,20 +2675,18 @@ static void fbnic_enable_rcq(struct fbnic_napi_vector *nv,
{
	struct fbnic_net *fbn = netdev_priv(nv->napi.dev);
	u32 log_size = fls(rcq->size_mask);
	u32 hds_thresh = fbn->hds_thresh;
	u32 rcq_ctl = 0;

	fbnic_config_drop_mode_rcq(nv, rcq, fbn->tx_pause);
	bool hdr_split;
	u32 hds_thresh;

	/* Force lower bound on MAX_HEADER_BYTES. Below this, all frames should
	 * be split at L4. It would also result in the frames being split at
	 * L2/L3 depending on the frame size.
	 */
	if (fbn->hds_thresh < FBNIC_HDR_BYTES_MIN) {
		rcq_ctl = FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT;
		hds_thresh = FBNIC_HDR_BYTES_MIN;
	}
	hdr_split = fbn->hds_thresh < FBNIC_HDR_BYTES_MIN;
	fbnic_config_drop_mode_rcq(nv, rcq, fbn->tx_pause, hdr_split);

	hds_thresh = max(fbn->hds_thresh, FBNIC_HDR_BYTES_MIN);
	rcq_ctl |= FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PADLEN_MASK, FBNIC_RX_PAD) |
		   FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_MAX_HDR_MASK, hds_thresh) |
		   FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PAYLD_OFF_MASK,
+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ struct fbnic_net;
	(4096 - FBNIC_RX_HROOM - FBNIC_RX_TROOM - FBNIC_RX_PAD)
#define FBNIC_HDS_THRESH_DEFAULT \
	(1536 - FBNIC_RX_PAD)
#define FBNIC_HDR_BYTES_MIN		128
#define FBNIC_HDR_BYTES_MIN		256

struct fbnic_pkt_buff {
	struct xdp_buff buff;
+18 −1
Original line number Diff line number Diff line
@@ -63,12 +63,29 @@ def check_tx_chunks(cfg) -> None:
    ksft_eq(socat.stdout.strip(), "hello\nworld")


def check_rx_hds(cfg) -> None:
    """Test HDS splitting across payload sizes."""
    require_devmem(cfg)

    for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]:
        port = rand_port()
        listen_cmd = f"{cfg.bin_local} -L -l -f {cfg.ifname} -s {cfg.addr} -p {port}"

        with bkg(listen_cmd, exit_wait=True) as ncdevmem:
            wait_port_listen(port)
            cmd(f"dd if=/dev/zero bs={size} count=1 2>/dev/null | " +
                f"socat -b {size} -u - TCP{cfg.addr_ipver}:{cfg.baddr}:{port},nodelay",
                host=cfg.remote, shell=True)

        ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}")


def main() -> None:
    with NetDrvEpEnv(__file__) as cfg:
        cfg.bin_local = path.abspath(path.dirname(__file__) + "/ncdevmem")
        cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)

        ksft_run([check_rx, check_tx, check_tx_chunks],
        ksft_run([check_rx, check_tx, check_tx_chunks, check_rx_hds],
                 args=(cfg, ))
    ksft_exit()

Loading