mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
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: Bobby Eshleman <bobbyeshleman@meta.com> ==================== Link: https://patch.msgid.link/20260211-fbnic-tcp-hds-fixes-v1-0-55d050e6f606@meta.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
22069735ff
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -338,9 +338,8 @@ 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);
|
||||
dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT,
|
||||
FBNIC_RCD_HDR_AL_DMA_HINT_L4);
|
||||
|
||||
rss_en_mask = fbnic_flow_hash_2_rss_en_mask(fbn, flow_type);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ static unsigned int ifindex;
|
|||
static unsigned int dmabuf_id;
|
||||
static uint32_t tx_dmabuf_id;
|
||||
static int waittime_ms = 500;
|
||||
static bool fail_on_linear;
|
||||
|
||||
/* System state loaded by current_config_load() */
|
||||
#define MAX_FLOWS 8
|
||||
|
|
@ -975,6 +976,11 @@ static int do_server(struct memory_buffer *mem)
|
|||
"SCM_DEVMEM_LINEAR. dmabuf_cmsg->frag_size=%u\n",
|
||||
dmabuf_cmsg->frag_size);
|
||||
|
||||
if (fail_on_linear) {
|
||||
pr_err("received SCM_DEVMEM_LINEAR but --fail-on-linear (-L) set");
|
||||
goto err_close_client;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1398,8 +1404,11 @@ int main(int argc, char *argv[])
|
|||
int is_server = 0, opt;
|
||||
int ret, err = 1;
|
||||
|
||||
while ((opt = getopt(argc, argv, "ls:c:p:v:q:t:f:z:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "Lls:c:p:v:q:t:f:z:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'L':
|
||||
fail_on_linear = true;
|
||||
break;
|
||||
case 'l':
|
||||
is_server = 1;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user