Skip to content

Commit b919f1e

Browse files
committed
Merge branch 'mlxsw-fixes'
Petr Machata says: ==================== mlxsw: Fixes In this patchset: - Tx header should be pushed for each packet which is transmitted via Spectrum ASICs. Patch #1 adds a missing call to skb_cow_head() to make sure that there is both enough room to push the Tx header and that the SKB header is not cloned and can be modified. - Commit b5b60bb ("mlxsw: pci: Use page pool for Rx buffers allocation") converted mlxsw to use page pool for Rx buffers allocation. Sync for CPU and for device should be done for Rx pages. In patches #2 and #3, add the missing calls to sync pages for, respectively, CPU and the device. - Patch #4 then fixes a bug to IPv6 GRE forwarding offload. Patch #5 adds a generic forwarding test that fails with mlxsw ports prior to the fix. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 04c20a9 + d7bd61f commit b919f1e

File tree

10 files changed

+212
-10
lines changed

10 files changed

+212
-10
lines changed

drivers/net/ethernet/mellanox/mlxsw/pci.c

+17-8
Original file line numberDiff line numberDiff line change
@@ -389,27 +389,34 @@ static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe,
389389
dma_unmap_single(&pdev->dev, mapaddr, frag_len, direction);
390390
}
391391

392-
static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[],
392+
static struct sk_buff *mlxsw_pci_rdq_build_skb(struct mlxsw_pci_queue *q,
393+
struct page *pages[],
393394
u16 byte_count)
394395
{
396+
struct mlxsw_pci_queue *cq = q->u.rdq.cq;
395397
unsigned int linear_data_size;
398+
struct page_pool *page_pool;
396399
struct sk_buff *skb;
397400
int page_index = 0;
398401
bool linear_only;
399402
void *data;
400403

404+
linear_only = byte_count + MLXSW_PCI_RX_BUF_SW_OVERHEAD <= PAGE_SIZE;
405+
linear_data_size = linear_only ? byte_count :
406+
PAGE_SIZE -
407+
MLXSW_PCI_RX_BUF_SW_OVERHEAD;
408+
409+
page_pool = cq->u.cq.page_pool;
410+
page_pool_dma_sync_for_cpu(page_pool, pages[page_index],
411+
MLXSW_PCI_SKB_HEADROOM, linear_data_size);
412+
401413
data = page_address(pages[page_index]);
402414
net_prefetch(data);
403415

404416
skb = napi_build_skb(data, PAGE_SIZE);
405417
if (unlikely(!skb))
406418
return ERR_PTR(-ENOMEM);
407419

408-
linear_only = byte_count + MLXSW_PCI_RX_BUF_SW_OVERHEAD <= PAGE_SIZE;
409-
linear_data_size = linear_only ? byte_count :
410-
PAGE_SIZE -
411-
MLXSW_PCI_RX_BUF_SW_OVERHEAD;
412-
413420
skb_reserve(skb, MLXSW_PCI_SKB_HEADROOM);
414421
skb_put(skb, linear_data_size);
415422

@@ -425,6 +432,7 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[],
425432

426433
page = pages[page_index];
427434
frag_size = min(byte_count, PAGE_SIZE);
435+
page_pool_dma_sync_for_cpu(page_pool, page, 0, frag_size);
428436
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
429437
page, 0, frag_size, PAGE_SIZE);
430438
byte_count -= frag_size;
@@ -760,7 +768,7 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
760768
if (err)
761769
goto out;
762770

763-
skb = mlxsw_pci_rdq_build_skb(pages, byte_count);
771+
skb = mlxsw_pci_rdq_build_skb(q, pages, byte_count);
764772
if (IS_ERR(skb)) {
765773
dev_err_ratelimited(&pdev->dev, "Failed to build skb for RDQ\n");
766774
mlxsw_pci_rdq_pages_recycle(q, pages, num_sg_entries);
@@ -988,12 +996,13 @@ static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q,
988996
if (cq_type != MLXSW_PCI_CQ_RDQ)
989997
return 0;
990998

991-
pp_params.flags = PP_FLAG_DMA_MAP;
999+
pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
9921000
pp_params.pool_size = MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries;
9931001
pp_params.nid = dev_to_node(&mlxsw_pci->pdev->dev);
9941002
pp_params.dev = &mlxsw_pci->pdev->dev;
9951003
pp_params.napi = &q->u.cq.napi;
9961004
pp_params.dma_dir = DMA_FROM_DEVICE;
1005+
pp_params.max_len = PAGE_SIZE;
9971006

9981007
page_pool = page_pool_create(&pp_params);
9991008
if (IS_ERR(page_pool))

drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c

+24-2
Original file line numberDiff line numberDiff line change
@@ -481,11 +481,33 @@ mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
481481
struct mlxsw_sp_ipip_entry *ipip_entry,
482482
struct netlink_ext_ack *extack)
483483
{
484+
u32 new_kvdl_index, old_kvdl_index = ipip_entry->dip_kvdl_index;
485+
struct in6_addr old_addr6 = ipip_entry->parms.daddr.addr6;
484486
struct mlxsw_sp_ipip_parms new_parms;
487+
int err;
485488

486489
new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev);
487-
return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
488-
&new_parms, extack);
490+
491+
err = mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp,
492+
&new_parms.daddr.addr6,
493+
&new_kvdl_index);
494+
if (err)
495+
return err;
496+
ipip_entry->dip_kvdl_index = new_kvdl_index;
497+
498+
err = mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
499+
&new_parms, extack);
500+
if (err)
501+
goto err_change_gre;
502+
503+
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &old_addr6);
504+
505+
return 0;
506+
507+
err_change_gre:
508+
ipip_entry->dip_kvdl_index = old_kvdl_index;
509+
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &new_parms.daddr.addr6);
510+
return err;
489511
}
490512

491513
static int

drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "spectrum.h"
1717
#include "spectrum_ptp.h"
1818
#include "core.h"
19+
#include "txheader.h"
1920

2021
#define MLXSW_SP1_PTP_CLOCK_CYCLES_SHIFT 29
2122
#define MLXSW_SP1_PTP_CLOCK_FREQ_KHZ 156257 /* 6.4nSec */
@@ -1684,6 +1685,12 @@ int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,
16841685
struct sk_buff *skb,
16851686
const struct mlxsw_tx_info *tx_info)
16861687
{
1688+
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
1689+
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
1690+
dev_kfree_skb_any(skb);
1691+
return -ENOMEM;
1692+
}
1693+
16871694
mlxsw_sp_txhdr_construct(skb, tx_info);
16881695
return 0;
16891696
}

tools/testing/selftests/net/forwarding/ip6gre_flat.sh

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ALL_TESTS="
99
gre_flat
1010
gre_mtu_change
11+
gre_flat_remote_change
1112
"
1213

1314
NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change()
4445
test_mtu_change
4546
}
4647

48+
gre_flat_remote_change()
49+
{
50+
flat_remote_change
51+
52+
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 (new remote)"
53+
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 (new remote)"
54+
55+
flat_remote_restore
56+
57+
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 (old remote)"
58+
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 (old remote)"
59+
}
60+
4761
cleanup()
4862
{
4963
pre_cleanup

tools/testing/selftests/net/forwarding/ip6gre_flat_key.sh

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ALL_TESTS="
99
gre_flat
1010
gre_mtu_change
11+
gre_flat_remote_change
1112
"
1213

1314
NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change()
4445
test_mtu_change
4546
}
4647

48+
gre_flat_remote_change()
49+
{
50+
flat_remote_change
51+
52+
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with key (new remote)"
53+
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with key (new remote)"
54+
55+
flat_remote_restore
56+
57+
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with key (old remote)"
58+
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with key (old remote)"
59+
}
60+
4761
cleanup()
4862
{
4963
pre_cleanup

tools/testing/selftests/net/forwarding/ip6gre_flat_keys.sh

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ALL_TESTS="
99
gre_flat
1010
gre_mtu_change
11+
gre_flat_remote_change
1112
"
1213

1314
NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change()
4445
test_mtu_change gre
4546
}
4647

48+
gre_flat_remote_change()
49+
{
50+
flat_remote_change
51+
52+
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with ikey/okey (new remote)"
53+
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with ikey/okey (new remote)"
54+
55+
flat_remote_restore
56+
57+
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with ikey/okey (old remote)"
58+
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with ikey/okey (old remote)"
59+
}
60+
4761
cleanup()
4862
{
4963
pre_cleanup

tools/testing/selftests/net/forwarding/ip6gre_hier.sh

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ALL_TESTS="
99
gre_hier
1010
gre_mtu_change
11+
gre_hier_remote_change
1112
"
1213

1314
NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change()
4445
test_mtu_change gre
4546
}
4647

48+
gre_hier_remote_change()
49+
{
50+
hier_remote_change
51+
52+
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 (new remote)"
53+
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 (new remote)"
54+
55+
hier_remote_restore
56+
57+
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 (old remote)"
58+
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 (old remote)"
59+
}
60+
4761
cleanup()
4862
{
4963
pre_cleanup

tools/testing/selftests/net/forwarding/ip6gre_hier_key.sh

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ALL_TESTS="
99
gre_hier
1010
gre_mtu_change
11+
gre_hier_remote_change
1112
"
1213

1314
NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change()
4445
test_mtu_change gre
4546
}
4647

48+
gre_hier_remote_change()
49+
{
50+
hier_remote_change
51+
52+
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with key (new remote)"
53+
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with key (new remote)"
54+
55+
hier_remote_restore
56+
57+
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with key (old remote)"
58+
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with key (old remote)"
59+
}
60+
4761
cleanup()
4862
{
4963
pre_cleanup

tools/testing/selftests/net/forwarding/ip6gre_hier_keys.sh

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ALL_TESTS="
99
gre_hier
1010
gre_mtu_change
11+
gre_hier_remote_change
1112
"
1213

1314
NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change()
4445
test_mtu_change gre
4546
}
4647

48+
gre_hier_remote_change()
49+
{
50+
hier_remote_change
51+
52+
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with ikey/okey (new remote)"
53+
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with ikey/okey (new remote)"
54+
55+
hier_remote_restore
56+
57+
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with ikey/okey (old remote)"
58+
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with ikey/okey (old remote)"
59+
}
60+
4761
cleanup()
4862
{
4963
pre_cleanup

tools/testing/selftests/net/forwarding/ip6gre_lib.sh

+80
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,83 @@ test_mtu_change()
436436
check_err $?
437437
log_test "ping GRE IPv6, packet size 1800 after MTU change"
438438
}
439+
440+
topo_flat_remote_change()
441+
{
442+
local old1=$1; shift
443+
local new1=$1; shift
444+
local old2=$1; shift
445+
local new2=$1; shift
446+
447+
ip link set dev g1a type ip6gre local $new1 remote $new2
448+
__addr_add_del g1a add "$new1/128"
449+
__addr_add_del g1a del "$old1/128"
450+
ip -6 route add $new2/128 via 2001:db8:10::2
451+
ip -6 route del $old2/128
452+
453+
ip link set dev g2a type ip6gre local $new2 remote $new1
454+
__addr_add_del g2a add "$new2/128"
455+
__addr_add_del g2a del "$old2/128"
456+
ip -6 route add vrf v$ol2 $new1/128 via 2001:db8:10::1
457+
ip -6 route del vrf v$ol2 $old1/128
458+
}
459+
460+
flat_remote_change()
461+
{
462+
local old1=2001:db8:3::1
463+
local new1=2001:db8:3::10
464+
local old2=2001:db8:3::2
465+
local new2=2001:db8:3::20
466+
467+
topo_flat_remote_change $old1 $new1 $old2 $new2
468+
}
469+
470+
flat_remote_restore()
471+
{
472+
local old1=2001:db8:3::10
473+
local new1=2001:db8:3::1
474+
local old2=2001:db8:3::20
475+
local new2=2001:db8:3::2
476+
477+
topo_flat_remote_change $old1 $new1 $old2 $new2
478+
}
479+
480+
topo_hier_remote_change()
481+
{
482+
local old1=$1; shift
483+
local new1=$1; shift
484+
local old2=$1; shift
485+
local new2=$1; shift
486+
487+
__addr_add_del dummy1 del "$old1/64"
488+
__addr_add_del dummy1 add "$new1/64"
489+
ip link set dev g1a type ip6gre local $new1 remote $new2
490+
ip -6 route add vrf v$ul1 $new2/128 via 2001:db8:10::2
491+
ip -6 route del vrf v$ul1 $old2/128
492+
493+
__addr_add_del dummy2 del "$old2/64"
494+
__addr_add_del dummy2 add "$new2/64"
495+
ip link set dev g2a type ip6gre local $new2 remote $new1
496+
ip -6 route add vrf v$ul2 $new1/128 via 2001:db8:10::1
497+
ip -6 route del vrf v$ul2 $old1/128
498+
}
499+
500+
hier_remote_change()
501+
{
502+
local old1=2001:db8:3::1
503+
local new1=2001:db8:3::10
504+
local old2=2001:db8:3::2
505+
local new2=2001:db8:3::20
506+
507+
topo_hier_remote_change $old1 $new1 $old2 $new2
508+
}
509+
510+
hier_remote_restore()
511+
{
512+
local old1=2001:db8:3::10
513+
local new1=2001:db8:3::1
514+
local old2=2001:db8:3::20
515+
local new2=2001:db8:3::2
516+
517+
topo_hier_remote_change $old1 $new1 $old2 $new2
518+
}

0 commit comments

Comments
 (0)