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 b5b60bb491
("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/cover.1729866134.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
b919f1e54e
@ -389,15 +389,27 @@ static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe,
|
||||
dma_unmap_single(&pdev->dev, mapaddr, frag_len, direction);
|
||||
}
|
||||
|
||||
static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[],
|
||||
static struct sk_buff *mlxsw_pci_rdq_build_skb(struct mlxsw_pci_queue *q,
|
||||
struct page *pages[],
|
||||
u16 byte_count)
|
||||
{
|
||||
struct mlxsw_pci_queue *cq = q->u.rdq.cq;
|
||||
unsigned int linear_data_size;
|
||||
struct page_pool *page_pool;
|
||||
struct sk_buff *skb;
|
||||
int page_index = 0;
|
||||
bool linear_only;
|
||||
void *data;
|
||||
|
||||
linear_only = byte_count + MLXSW_PCI_RX_BUF_SW_OVERHEAD <= PAGE_SIZE;
|
||||
linear_data_size = linear_only ? byte_count :
|
||||
PAGE_SIZE -
|
||||
MLXSW_PCI_RX_BUF_SW_OVERHEAD;
|
||||
|
||||
page_pool = cq->u.cq.page_pool;
|
||||
page_pool_dma_sync_for_cpu(page_pool, pages[page_index],
|
||||
MLXSW_PCI_SKB_HEADROOM, linear_data_size);
|
||||
|
||||
data = page_address(pages[page_index]);
|
||||
net_prefetch(data);
|
||||
|
||||
@ -405,11 +417,6 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[],
|
||||
if (unlikely(!skb))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
linear_only = byte_count + MLXSW_PCI_RX_BUF_SW_OVERHEAD <= PAGE_SIZE;
|
||||
linear_data_size = linear_only ? byte_count :
|
||||
PAGE_SIZE -
|
||||
MLXSW_PCI_RX_BUF_SW_OVERHEAD;
|
||||
|
||||
skb_reserve(skb, MLXSW_PCI_SKB_HEADROOM);
|
||||
skb_put(skb, linear_data_size);
|
||||
|
||||
@ -425,6 +432,7 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[],
|
||||
|
||||
page = pages[page_index];
|
||||
frag_size = min(byte_count, PAGE_SIZE);
|
||||
page_pool_dma_sync_for_cpu(page_pool, page, 0, frag_size);
|
||||
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
||||
page, 0, frag_size, PAGE_SIZE);
|
||||
byte_count -= frag_size;
|
||||
@ -760,7 +768,7 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
skb = mlxsw_pci_rdq_build_skb(pages, byte_count);
|
||||
skb = mlxsw_pci_rdq_build_skb(q, pages, byte_count);
|
||||
if (IS_ERR(skb)) {
|
||||
dev_err_ratelimited(&pdev->dev, "Failed to build skb for RDQ\n");
|
||||
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,
|
||||
if (cq_type != MLXSW_PCI_CQ_RDQ)
|
||||
return 0;
|
||||
|
||||
pp_params.flags = PP_FLAG_DMA_MAP;
|
||||
pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
|
||||
pp_params.pool_size = MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries;
|
||||
pp_params.nid = dev_to_node(&mlxsw_pci->pdev->dev);
|
||||
pp_params.dev = &mlxsw_pci->pdev->dev;
|
||||
pp_params.napi = &q->u.cq.napi;
|
||||
pp_params.dma_dir = DMA_FROM_DEVICE;
|
||||
pp_params.max_len = PAGE_SIZE;
|
||||
|
||||
page_pool = page_pool_create(&pp_params);
|
||||
if (IS_ERR(page_pool))
|
||||
|
@ -481,11 +481,33 @@ mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_ipip_entry *ipip_entry,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u32 new_kvdl_index, old_kvdl_index = ipip_entry->dip_kvdl_index;
|
||||
struct in6_addr old_addr6 = ipip_entry->parms.daddr.addr6;
|
||||
struct mlxsw_sp_ipip_parms new_parms;
|
||||
int err;
|
||||
|
||||
new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev);
|
||||
return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
|
||||
&new_parms, extack);
|
||||
|
||||
err = mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp,
|
||||
&new_parms.daddr.addr6,
|
||||
&new_kvdl_index);
|
||||
if (err)
|
||||
return err;
|
||||
ipip_entry->dip_kvdl_index = new_kvdl_index;
|
||||
|
||||
err = mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
|
||||
&new_parms, extack);
|
||||
if (err)
|
||||
goto err_change_gre;
|
||||
|
||||
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &old_addr6);
|
||||
|
||||
return 0;
|
||||
|
||||
err_change_gre:
|
||||
ipip_entry->dip_kvdl_index = old_kvdl_index;
|
||||
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &new_parms.daddr.addr6);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "spectrum.h"
|
||||
#include "spectrum_ptp.h"
|
||||
#include "core.h"
|
||||
#include "txheader.h"
|
||||
|
||||
#define MLXSW_SP1_PTP_CLOCK_CYCLES_SHIFT 29
|
||||
#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,
|
||||
struct sk_buff *skb,
|
||||
const struct mlxsw_tx_info *tx_info)
|
||||
{
|
||||
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
|
||||
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
|
||||
dev_kfree_skb_any(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mlxsw_sp_txhdr_construct(skb, tx_info);
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
ALL_TESTS="
|
||||
gre_flat
|
||||
gre_mtu_change
|
||||
gre_flat_remote_change
|
||||
"
|
||||
|
||||
NUM_NETIFS=6
|
||||
@ -44,6 +45,19 @@ gre_mtu_change()
|
||||
test_mtu_change
|
||||
}
|
||||
|
||||
gre_flat_remote_change()
|
||||
{
|
||||
flat_remote_change
|
||||
|
||||
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 (new remote)"
|
||||
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 (new remote)"
|
||||
|
||||
flat_remote_restore
|
||||
|
||||
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 (old remote)"
|
||||
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 (old remote)"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
@ -8,6 +8,7 @@
|
||||
ALL_TESTS="
|
||||
gre_flat
|
||||
gre_mtu_change
|
||||
gre_flat_remote_change
|
||||
"
|
||||
|
||||
NUM_NETIFS=6
|
||||
@ -44,6 +45,19 @@ gre_mtu_change()
|
||||
test_mtu_change
|
||||
}
|
||||
|
||||
gre_flat_remote_change()
|
||||
{
|
||||
flat_remote_change
|
||||
|
||||
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with key (new remote)"
|
||||
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with key (new remote)"
|
||||
|
||||
flat_remote_restore
|
||||
|
||||
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with key (old remote)"
|
||||
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with key (old remote)"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
@ -8,6 +8,7 @@
|
||||
ALL_TESTS="
|
||||
gre_flat
|
||||
gre_mtu_change
|
||||
gre_flat_remote_change
|
||||
"
|
||||
|
||||
NUM_NETIFS=6
|
||||
@ -44,6 +45,19 @@ gre_mtu_change()
|
||||
test_mtu_change gre
|
||||
}
|
||||
|
||||
gre_flat_remote_change()
|
||||
{
|
||||
flat_remote_change
|
||||
|
||||
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with ikey/okey (new remote)"
|
||||
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with ikey/okey (new remote)"
|
||||
|
||||
flat_remote_restore
|
||||
|
||||
test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with ikey/okey (old remote)"
|
||||
test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with ikey/okey (old remote)"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
@ -8,6 +8,7 @@
|
||||
ALL_TESTS="
|
||||
gre_hier
|
||||
gre_mtu_change
|
||||
gre_hier_remote_change
|
||||
"
|
||||
|
||||
NUM_NETIFS=6
|
||||
@ -44,6 +45,19 @@ gre_mtu_change()
|
||||
test_mtu_change gre
|
||||
}
|
||||
|
||||
gre_hier_remote_change()
|
||||
{
|
||||
hier_remote_change
|
||||
|
||||
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 (new remote)"
|
||||
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 (new remote)"
|
||||
|
||||
hier_remote_restore
|
||||
|
||||
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 (old remote)"
|
||||
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 (old remote)"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
@ -8,6 +8,7 @@
|
||||
ALL_TESTS="
|
||||
gre_hier
|
||||
gre_mtu_change
|
||||
gre_hier_remote_change
|
||||
"
|
||||
|
||||
NUM_NETIFS=6
|
||||
@ -44,6 +45,19 @@ gre_mtu_change()
|
||||
test_mtu_change gre
|
||||
}
|
||||
|
||||
gre_hier_remote_change()
|
||||
{
|
||||
hier_remote_change
|
||||
|
||||
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with key (new remote)"
|
||||
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with key (new remote)"
|
||||
|
||||
hier_remote_restore
|
||||
|
||||
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with key (old remote)"
|
||||
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with key (old remote)"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
@ -8,6 +8,7 @@
|
||||
ALL_TESTS="
|
||||
gre_hier
|
||||
gre_mtu_change
|
||||
gre_hier_remote_change
|
||||
"
|
||||
|
||||
NUM_NETIFS=6
|
||||
@ -44,6 +45,19 @@ gre_mtu_change()
|
||||
test_mtu_change gre
|
||||
}
|
||||
|
||||
gre_hier_remote_change()
|
||||
{
|
||||
hier_remote_change
|
||||
|
||||
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with ikey/okey (new remote)"
|
||||
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with ikey/okey (new remote)"
|
||||
|
||||
hier_remote_restore
|
||||
|
||||
test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with ikey/okey (old remote)"
|
||||
test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with ikey/okey (old remote)"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
@ -436,3 +436,83 @@ test_mtu_change()
|
||||
check_err $?
|
||||
log_test "ping GRE IPv6, packet size 1800 after MTU change"
|
||||
}
|
||||
|
||||
topo_flat_remote_change()
|
||||
{
|
||||
local old1=$1; shift
|
||||
local new1=$1; shift
|
||||
local old2=$1; shift
|
||||
local new2=$1; shift
|
||||
|
||||
ip link set dev g1a type ip6gre local $new1 remote $new2
|
||||
__addr_add_del g1a add "$new1/128"
|
||||
__addr_add_del g1a del "$old1/128"
|
||||
ip -6 route add $new2/128 via 2001:db8:10::2
|
||||
ip -6 route del $old2/128
|
||||
|
||||
ip link set dev g2a type ip6gre local $new2 remote $new1
|
||||
__addr_add_del g2a add "$new2/128"
|
||||
__addr_add_del g2a del "$old2/128"
|
||||
ip -6 route add vrf v$ol2 $new1/128 via 2001:db8:10::1
|
||||
ip -6 route del vrf v$ol2 $old1/128
|
||||
}
|
||||
|
||||
flat_remote_change()
|
||||
{
|
||||
local old1=2001:db8:3::1
|
||||
local new1=2001:db8:3::10
|
||||
local old2=2001:db8:3::2
|
||||
local new2=2001:db8:3::20
|
||||
|
||||
topo_flat_remote_change $old1 $new1 $old2 $new2
|
||||
}
|
||||
|
||||
flat_remote_restore()
|
||||
{
|
||||
local old1=2001:db8:3::10
|
||||
local new1=2001:db8:3::1
|
||||
local old2=2001:db8:3::20
|
||||
local new2=2001:db8:3::2
|
||||
|
||||
topo_flat_remote_change $old1 $new1 $old2 $new2
|
||||
}
|
||||
|
||||
topo_hier_remote_change()
|
||||
{
|
||||
local old1=$1; shift
|
||||
local new1=$1; shift
|
||||
local old2=$1; shift
|
||||
local new2=$1; shift
|
||||
|
||||
__addr_add_del dummy1 del "$old1/64"
|
||||
__addr_add_del dummy1 add "$new1/64"
|
||||
ip link set dev g1a type ip6gre local $new1 remote $new2
|
||||
ip -6 route add vrf v$ul1 $new2/128 via 2001:db8:10::2
|
||||
ip -6 route del vrf v$ul1 $old2/128
|
||||
|
||||
__addr_add_del dummy2 del "$old2/64"
|
||||
__addr_add_del dummy2 add "$new2/64"
|
||||
ip link set dev g2a type ip6gre local $new2 remote $new1
|
||||
ip -6 route add vrf v$ul2 $new1/128 via 2001:db8:10::1
|
||||
ip -6 route del vrf v$ul2 $old1/128
|
||||
}
|
||||
|
||||
hier_remote_change()
|
||||
{
|
||||
local old1=2001:db8:3::1
|
||||
local new1=2001:db8:3::10
|
||||
local old2=2001:db8:3::2
|
||||
local new2=2001:db8:3::20
|
||||
|
||||
topo_hier_remote_change $old1 $new1 $old2 $new2
|
||||
}
|
||||
|
||||
hier_remote_restore()
|
||||
{
|
||||
local old1=2001:db8:3::10
|
||||
local new1=2001:db8:3::1
|
||||
local old2=2001:db8:3::20
|
||||
local new2=2001:db8:3::2
|
||||
|
||||
topo_hier_remote_change $old1 $new1 $old2 $new2
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user