Netdev List
 help / color / mirror / Atom feed
* [PATCH] PCI: allow drivers to limit the number of VFs to 0
From: Jakub Kicinski @ 2018-03-29 18:22 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, netdev, Sathya Perla, Felix Manlunas, alexander.duyck,
	john.fastabend, Jacob Keller, Donald Dutile, oss-drivers,
	Jakub Kicinski

Some user space depends on driver allowing sriov_totalvfs to be
enabled.  For devices which VF support depends on loaded FW we
have the pci_sriov_{g,s}et_totalvfs() API.  However, this API
uses 0 as a special "unset" value, meaning drivers can't limit
sriov_totalvfs to 0.  Change the special value to be U16_MAX.
Use simple min() to determine actual totalvfs.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_main.c | 6 +++---
 drivers/pci/iov.c                             | 6 ++----
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index c4b1f344b4da..dcd6e208a155 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -123,7 +123,7 @@ static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
 		return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
 
 	pf->limit_vfs = ~0;
-	pci_sriov_set_totalvfs(pf->pdev, 0); /* 0 is unset */
+	pci_sriov_set_totalvfs(pf->pdev, ~0);
 	/* Allow any setting for backwards compatibility if symbol not found */
 	if (err == -ENOENT)
 		return 0;
@@ -537,7 +537,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
 err_net_remove:
 	nfp_net_pci_remove(pf);
 err_sriov_unlimit:
-	pci_sriov_set_totalvfs(pf->pdev, 0);
+	pci_sriov_set_totalvfs(pf->pdev, ~0);
 err_fw_unload:
 	kfree(pf->rtbl);
 	nfp_mip_close(pf->mip);
@@ -570,7 +570,7 @@ static void nfp_pci_remove(struct pci_dev *pdev)
 	nfp_hwmon_unregister(pf);
 
 	nfp_pcie_sriov_disable(pdev);
-	pci_sriov_set_totalvfs(pf->pdev, 0);
+	pci_sriov_set_totalvfs(pf->pdev, ~0);
 
 	nfp_net_pci_remove(pf);
 
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 677924ae0350..aa3dfe3ecd68 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -446,6 +446,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
 	pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device);
 	iov->pgsz = pgsz;
 	iov->self = dev;
+	iov->driver_max_VFs = U16_MAX;
 	iov->drivers_autoprobe = true;
 	pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
 	pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
@@ -801,9 +802,6 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev)
 	if (!dev->is_physfn)
 		return 0;
 
-	if (dev->sriov->driver_max_VFs)
-		return dev->sriov->driver_max_VFs;
-
-	return dev->sriov->total_VFs;
+	return min(dev->sriov->total_VFs, dev->sriov->driver_max_VFs);
 }
 EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
-- 
2.16.2

^ permalink raw reply related

* Re: [PATCH v2 net-next] qed*: Utilize FW 8.33.11.0
From: David Miller @ 2018-03-29 18:18 UTC (permalink / raw)
  To: Michal.Kalderon
  Cc: netdev, linux-rdma, linux-scsi, Tomer.Tayar, Manish.Rangankar,
	Ariel.Elior
In-Reply-To: <1522226536-9812-1-git-send-email-Michal.Kalderon@cavium.com>

From: Michal Kalderon <Michal.Kalderon@cavium.com>
Date: Wed, 28 Mar 2018 11:42:16 +0300

> This FW contains several fixes and features
> 
> RDMA Features
> - SRQ support
> - XRC support
> - Memory window support
> - RDMA low latency queue support
> - RDMA bonding support
> 
> RDMA bug fixes
> - RDMA remote invalidate during retransmit fix
> - iWARP MPA connect interop issue with RTR fix
> - iWARP Legacy DPM support
> - Fix MPA reject flow
> - iWARP error handling
> - RQ WQE validation checks
> 
> MISC
> - Fix some HSI types endianity
> - New Restriction: vlan insertion in core_tx_bd_data can't be set
>   for LB packets
> 
> ETH
> - HW QoS offload support
> - Fix vlan, dcb and sriov flow of VF sending a packet with
>   inband VLAN tag instead of default VLAN
> - Allow GRE version 1 offloads in RX flow
> - Allow VXLAN steering
> 
> iSCSI / FcoE
> - Fix bd availability checking flow
> - Support 256th sge proerly in iscsi/fcoe retransmit
> - Performance improvement
> - Fix handle iSCSI command arrival with AHS and with immediate
> - Fix ipv6 traffic class configuration
> 
> DEBUG
> - Update debug utilities
> 
> Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
> Signed-off-by: Tomer Tayar <Tomer.Tayar@cavium.com>
> Signed-off-by: Manish Rangankar <Manish.Rangankar@cavium.com>
> Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
> ---
> Changes from v1
> 	Remove version bump and qedr module version addition

Applied.

^ permalink raw reply

* Re: [PATCH net-next] ipv6: export ip6 fragments sysctl to unprivileged users
From: David Miller @ 2018-03-29 18:14 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, eric.dumazet, kernel
In-Reply-To: <20180328024942.147207-1-edumazet@google.com>

From: Eric Dumazet <edumazet@google.com>
Date: Tue, 27 Mar 2018 19:49:42 -0700

> IPv4 was changed in commit 52a773d645e9 ("net: Export ip fragment
> sysctl to unprivileged users")
> 
> The only sysctl that is not per-netns is not used :
> ip6frag_secret_interval
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] liquidio: Prioritize control messages
From: David Miller @ 2018-03-29 18:14 UTC (permalink / raw)
  To: felix.manlunas
  Cc: netdev, raghu.vatsavayi, derek.chickles, satananda.burla,
	intiyaz.basha
In-Reply-To: <20180328022518.GA9011@felix-thinkpad.cavium.com>

From: Felix Manlunas <felix.manlunas@cavium.com>
Date: Tue, 27 Mar 2018 19:25:18 -0700

> From: Intiyaz Basha <intiyaz.basha@cavium.com>
> 
> During heavy tx traffic, control messages (sent by liquidio driver to NIC
> firmware) sometimes do not get processed in a timely manner.  Reason is:
> the low-level metadata of control messages and that of egress network
> packets indicate that they have the same priority.
> 
> Fix it by setting a higher priority for control messages through the new
> ctrl_qpg field in the oct_txpciq struct.  It is the NIC firmware that does
> the actual setting of priority by writing to the new ctrl_qpg field; the
> host driver treats that value as opaque and just assigns it to pki_ih3->qpg
> 
> Signed-off-by: Intiyaz Basha <intiyaz.basha@cavium.com>
> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com>

Applied.

^ permalink raw reply

* [PATCH V2 net-next] liquidio: prevent rx queues from getting stalled
From: Felix Manlunas @ 2018-03-29 18:13 UTC (permalink / raw)
  To: davem
  Cc: netdev, raghu.vatsavayi, derek.chickles, satananda.burla,
	felix.manlunas

From: Raghu Vatsavayi <raghu.vatsavayi@cavium.com>

This commit has fix for RX traffic issues when we stress test the driver
with continuous ifconfig up/down under very high traffic conditions.

Reason for the issue is that, in existing liquidio_stop function NAPI is
disabled even before actual FW/HW interface is brought down via
send_rx_ctrl_cmd(lio, 0). Between time frame of NAPI disable and actual
interface down in firmware, firmware continuously enqueues rx traffic to
host. When interrupt happens for new packets, host irq handler fails in
scheduling NAPI as the NAPI is already disabled.

After "ifconfig <iface> up", Host re-enables NAPI but cannot schedule it
until it receives another Rx interrupt. Host never receives Rx interrupt as
it never cleared the Rx interrupt it received during interface down
operation. NIC Rx interrupt gets cleared only when Host processes queue and
clears the queue counts. Above anomaly leads to other issues like packet
overflow in FW/HW queues, backpressure.

Fix:
This commit fixes this issue by disabling NAPI only after informing
firmware to stop queueing packets to host via send_rx_ctrl_cmd(lio, 0).
send_rx_ctrl_cmd is not visible in the patch as it is already there in the
code. The DOWN command also waits for any pending packets to be processed
by NAPI so that the deadlock will not occur.

Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@cavium.com>
Acked-by: Derek Chickles <derek.chickles@cavium.com>
Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com>
---
Patch Change Log:
  V1 -> V2:
    Revised the subject line and patch description to add clarity.
    No change in the actual code.

 drivers/net/ethernet/cavium/liquidio/lio_core.c    | 23 ++++++++++++++++++++
 drivers/net/ethernet/cavium/liquidio/lio_main.c    | 25 +++++++++++++---------
 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 23 ++++++++++++--------
 .../net/ethernet/cavium/liquidio/octeon_network.h  |  1 +
 4 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 73e70e0..2a94eee 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -1146,3 +1146,26 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
 	octeon_free_soft_command(oct, sc);
 	return 0;
 }
+
+int lio_wait_for_clean_oq(struct octeon_device *oct)
+{
+	int retry = 100, pending_pkts = 0;
+	int idx;
+
+	do {
+		pending_pkts = 0;
+
+		for (idx = 0; idx < MAX_OCTEON_OUTPUT_QUEUES(oct); idx++) {
+			if (!(oct->io_qmask.oq & BIT_ULL(idx)))
+				continue;
+			pending_pkts +=
+				atomic_read(&oct->droq[idx]->pkts_pending);
+		}
+
+		if (pending_pkts > 0)
+			schedule_timeout_uninterruptible(1);
+
+	} while (retry-- && pending_pkts);
+
+	return pending_pkts;
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 43c5ba0..603a144 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2084,16 +2084,6 @@ static int liquidio_stop(struct net_device *netdev)
 	struct octeon_device *oct = lio->oct_dev;
 	struct napi_struct *napi, *n;
 
-	if (oct->props[lio->ifidx].napi_enabled) {
-		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
-			napi_disable(napi);
-
-		oct->props[lio->ifidx].napi_enabled = 0;
-
-		if (OCTEON_CN23XX_PF(oct))
-			oct->droq[0]->ops.poll_mode = 0;
-	}
-
 	ifstate_reset(lio, LIO_IFSTATE_RUNNING);
 
 	netif_tx_disable(netdev);
@@ -2119,6 +2109,21 @@ static int liquidio_stop(struct net_device *netdev)
 		lio->ptp_clock = NULL;
 	}
 
+	/* Wait for any pending Rx descriptors */
+	if (lio_wait_for_clean_oq(oct))
+		netif_info(lio, rx_err, lio->netdev,
+			   "Proceeding with stop interface after partial RX desc processing\n");
+
+	if (oct->props[lio->ifidx].napi_enabled == 1) {
+		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+			napi_disable(napi);
+
+		oct->props[lio->ifidx].napi_enabled = 0;
+
+		if (OCTEON_CN23XX_PF(oct))
+			oct->droq[0]->ops.poll_mode = 0;
+	}
+
 	dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
 	return 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index dc62698..f92dfa4 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1138,15 +1138,6 @@ static int liquidio_stop(struct net_device *netdev)
 	/* tell Octeon to stop forwarding packets to host */
 	send_rx_ctrl_cmd(lio, 0);
 
-	if (oct->props[lio->ifidx].napi_enabled) {
-		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
-			napi_disable(napi);
-
-		oct->props[lio->ifidx].napi_enabled = 0;
-
-		oct->droq[0]->ops.poll_mode = 0;
-	}
-
 	netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
 	/* Inform that netif carrier is down */
 	lio->intf_open = 0;
@@ -1159,6 +1150,20 @@ static int liquidio_stop(struct net_device *netdev)
 
 	stop_txqs(netdev);
 
+	/* Wait for any pending Rx descriptors */
+	if (lio_wait_for_clean_oq(oct))
+		netif_info(lio, rx_err, lio->netdev,
+			   "Proceeding with stop interface after partial RX desc processing\n");
+
+	if (oct->props[lio->ifidx].napi_enabled == 1) {
+		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+			napi_disable(napi);
+
+		oct->props[lio->ifidx].napi_enabled = 0;
+
+		oct->droq[0]->ops.poll_mode = 0;
+	}
+
 	dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
 	return 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
index 8782206..4069710 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
@@ -190,6 +190,7 @@ irqreturn_t liquidio_msix_intr_handler(int irq __attribute__((unused)),
 
 int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs);
 
+int lio_wait_for_clean_oq(struct octeon_device *oct);
 /**
  * \brief Register ethtool operations
  * @param netdev    pointer to network device

^ permalink raw reply related

* Re: [PATCH net-next 6/6] netdevsim: Add simple FIB resource controller via devlink
From: David Miller @ 2018-03-29 18:11 UTC (permalink / raw)
  To: jakub.kicinski; +Cc: dsa, netdev, roopa, shm, jiri, idosch, andy.roulin
In-Reply-To: <20180327183450.34d6e9b6@cakuba.netronome.com>

From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Tue, 27 Mar 2018 18:34:50 -0700

> On Tue, 27 Mar 2018 18:22:00 -0700, David Ahern wrote:
>> +void nsim_devlink_setup(struct netdevsim *ns)
>> +{
 ...
> nit: DaveM expressed preference to not have silent failures in a
>      discussion about DebugFS, not sure it applies here, but why not
>      handle errors?

Yes it is a concern.

David please address this as a follow-up.

Thanks.

^ permalink raw reply

* Re: [PATCH net-next 0/6] net: Allow FIB notifiers to fail add and replace
From: David Miller @ 2018-03-29 18:11 UTC (permalink / raw)
  To: dsa; +Cc: netdev, roopa, shm, jiri, idosch, jakub.kicinski, andy.roulin
In-Reply-To: <20180328012200.15175-1-dsa@cumulusnetworks.com>

From: David Ahern <dsa@cumulusnetworks.com>
Date: Tue, 27 Mar 2018 18:21:54 -0700

> I wanted to revisit how resource overload is handled for hardware offload
> of FIB entries and rules. At the moment, the in-kernel fib notifier can
> tell a driver about a route or rule add, replace, and delete, but the
> notifier can not affect the action. Specifically, in the case of mlxsw
> if a route or rule add is going to overflow the ASIC resources the only
> recourse is to abort hardware offload. Aborting offload is akin to taking
> down the switch as the path from data plane to the control plane simply
> can not support the traffic bandwidth of the front panel ports. Further,
> the current state of FIB notifiers is inconsistent with other resources
> where a driver can affect a user request - e.g., enslavement of a port
> into a bridge or a VRF.
> 
> As a result of the work done over the past 3+ years, I believe we are
> at a point where we can bring consistency to the stack and offloads,
> and reliably allow the FIB notifiers to fail a request, pushing an error
> along with a suitable error message back to the user. Rather than
> aborting offload when the switch is out of resources, userspace is simply
> prevented from adding more routes and has a clear indication of why.
> 
> This set does not resolve the corner case where rules or routes not
> supported by the device are installed prior to the driver getting loaded
> and registering for FIB notifications. In that case, hardware offload has
> not been established and it can refuse to offload anything, sending
> errors back to userspace via extack. Since conceptually the driver owns
> the netdevices associated with its asic, this corner case mainly applies
> to unsupported rules and any races during the bringup phase.
> 
> Patch 1 fixes call_fib_notifiers to extract the errno from the encoded
> response from handlers.
> 
> Patches 2-5 allow the call to call_fib_notifiers to fail the add or
> replace of a route or rule.
> 
> Patch 6 adds a simple resource controller to netdevsim to illustrate
> how a FIB resource controller can limit the number of route entries.

Series applied, thanks David.

^ permalink raw reply

* Re: [PATCH 07/30] aio: add delayed cancel support
From: Christoph Hellwig @ 2018-03-29 18:08 UTC (permalink / raw)
  To: Al Viro
  Cc: Christoph Hellwig, Avi Kivity, linux-aio, linux-fsdevel, netdev,
	linux-api, linux-kernel
In-Reply-To: <20180329142506.GX30522@ZenIV.linux.org.uk>

On Thu, Mar 29, 2018 at 03:25:06PM +0100, Al Viro wrote:
> OK.  Let's leave that alone for now.  Re deferred cancels - AFAICS, we *must*
> remove the sucker from ctx->active_reqs before dropping ->ctx_lock.
> 
> As it is, you are creating a io_cancel()/io_cancel() race leading to double
> fput().  It's not that hard to fix; I can do that myself while applying your
> series (as described in previous posting - kiocb_cancel_locked() returning
> NULL or ERR_PTR() in non-deferred case and pointer to aio_kiocb removed from
> ->active_reqs in deferred one) or you could fix it in some other way and
> update your branch.

I think that is the right fix.  Let me resend so that I can test the
result first.

--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org.  For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply

* Re: [PATCH net-next] net/mlx4_en: CHECKSUM_COMPLETE support for fragments
From: David Miller @ 2018-03-29 18:07 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, eric.dumazet, willemb, tariqt
In-Reply-To: <20180327212114.164202-1-edumazet@google.com>

From: Eric Dumazet <edumazet@google.com>
Date: Tue, 27 Mar 2018 14:21:14 -0700

> Refine the RX check summing handling to propagate the
> hardware provided checksum so that we do not have to
> compute it later in software.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Tariq, please review.

^ permalink raw reply

* Vmbus series...
From: David Miller @ 2018-03-29 18:06 UTC (permalink / raw)
  To: longli; +Cc: netdev, linux-scsi


Please feel free put it in via the scsi tree:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [pull request][net-next 00/15] Mellanox, mlx5 mlx5-updates-2018-03-27
From: David Miller @ 2018-03-29 18:04 UTC (permalink / raw)
  To: saeedm; +Cc: netdev
In-Reply-To: <20180328004249.3796-1-saeedm@mellanox.com>

From: Saeed Mahameed <saeedm@mellanox.com>
Date: Tue, 27 Mar 2018 17:42:34 -0700

> This series contains Misc updates and cleanups for mlx5e rx path
> and SQ recovery feature for tx path.
> 
> For more information please see tag log below.
> 
> Please pull and let me know if there's any problem.

Pulled, thank you.

^ permalink raw reply

* Re: [iproute2-next 0/2] tipc: changes to addressing structure
From: David Ahern @ 2018-03-29 17:58 UTC (permalink / raw)
  To: Jon Maloy, davem, netdev
  Cc: mohan.krishna.ghanta.krishnamurthy, tung.q.nguyen, hoang.h.le,
	canh.d.luu, ying.xue, tipc-discussion
In-Reply-To: <01b6fe63-def9-4c67-cdb3-a88a07964f83@gmail.com>

On 3/29/18 11:52 AM, David Ahern wrote:
> On 3/28/18 10:52 AM, Jon Maloy wrote:
>> 1: We introduce ability to set/get 128-bit node identities
>> 2: We rename 'net id' to 'cluster id' in the command API, 
>>    of course in a compatible way.
>> 3: We print out all 32-bit node addresses as an integer in hex format,
>>    i.e., we remove the assumption about an internal structure.
>>
> 
> Applied to iproute2-next. Thanks,
> 

BTW, please consider adding json support to tipc. It will make tipc
command more robust to changes in output format.

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: bcmgenet: Fix coalescing settings handling
From: Florian Fainelli @ 2018-03-29 17:54 UTC (permalink / raw)
  To: Doug Berger, netdev
  Cc: davem, jaedon.shin, pgynther, Michael Chan, gospo, talgi, saeedm
In-Reply-To: <b8d41df2-8052-2f9e-8da7-b45c5d5ee768@gmail.com>

On 03/29/2018 10:51 AM, Doug Berger wrote:
> On 03/27/2018 12:47 PM, Florian Fainelli wrote:
>> There were a number of issues with setting the RX coalescing parameters:
>>
>> - we would not be preserving values that would have been configured
>>   across close/open calls, instead we would always reset to no timeout
>>   and 1 interrupt per packet, this would also prevent DIM from setting its
>>   default usec/pkts values
>>
>> - when adaptive RX would be turned on, we woud not be fetching the
>>   default parameters, we would stay with no timeout/1 packet per interrupt
>>   until the estimator kicks in and changes that
>>
>> - finally disabling adaptive RX coalescing while providing parameters
>>   would not be honored, and we would stay with whatever DIM had previously
>>   determined instead of the user requested parameters
>>
>> Fixes: 9f4ca05827a2 ("net: bcmgenet: Add support for adaptive RX coalescing")
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>>  drivers/net/ethernet/broadcom/genet/bcmgenet.c | 78 ++++++++++++++++++--------
>>  drivers/net/ethernet/broadcom/genet/bcmgenet.h |  4 +-
>>  2 files changed, 57 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> index 7db8edc643ec..76409debb796 100644
>> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> @@ -625,18 +625,18 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
>>  	return 0;
>>  }
>>  
>> -static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring)
>> +static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring,
>> +				     u32 usecs, u32 pkts)
>>  {
>>  	struct bcmgenet_priv *priv = ring->priv;
>>  	unsigned int i = ring->index;
>>  	u32 reg;
>>  
>> -	bcmgenet_rdma_ring_writel(priv, i, ring->dim.coal_pkts,
>> -				  DMA_MBUF_DONE_THRESH);
>> +	bcmgenet_rdma_ring_writel(priv, i, pkts, DMA_MBUF_DONE_THRESH);
>>  
>>  	reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
>>  	reg &= ~DMA_TIMEOUT_MASK;
>> -	reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192);
>> +	reg |= DIV_ROUND_UP(usecs * 1000, 8192);
>>  	bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
>>  }
>>  
>> @@ -645,6 +645,8 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
>>  {
>>  	struct bcmgenet_priv *priv = netdev_priv(dev);
>>  	struct bcmgenet_rx_ring *ring;
>> +	struct net_dim_cq_moder moder;
>> +	u32 usecs, pkts;
>>  	unsigned int i;
>>  
>>  	/* Base system clock is 125Mhz, DMA timeout is this reference clock
>> @@ -682,25 +684,37 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
>>  
>>  	for (i = 0; i < priv->hw_params->rx_queues; i++) {
>>  		ring = &priv->rx_rings[i];
>> -		ring->dim.coal_usecs = ec->rx_coalesce_usecs;
>> -		ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
>> -		if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
>> -			ring->dim.coal_pkts = 1;
>> -			ring->dim.coal_usecs = 0;
>> +
>> +		ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
>> +		ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
>> +		usecs = ring->rx_coalesce_usecs;
>> +		pkts = ring->rx_max_coalesced_frames;
>> +
>> +		if (ec->use_adaptive_rx_coalesce) {
>> +			moder = net_dim_get_def_profile(ring->dim.dim.mode);
>> +			usecs = moder.usec;
>> +			pkts = moder.pkts;
>>  		}
>> +
>>  		ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
>> -		bcmgenet_set_rx_coalesce(ring);
>> +		bcmgenet_set_rx_coalesce(ring, usecs, pkts);
> You might want to put this loop code in a separate function with ring
> and ec parameters

Indeed, that also itched me, v2 has this in a function:

http://patchwork.ozlabs.org/patch/892509/

(gmail coalescing threads, oh oh oh, what a good pun).

Thanks!
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: bcmgenet: Fix coalescing settings handling
From: Doug Berger @ 2018-03-29 17:53 UTC (permalink / raw)
  To: Florian Fainelli, netdev
  Cc: davem, jaedon.shin, pgynther, Michael Chan, gospo, talgi, saeedm
In-Reply-To: <b8d41df2-8052-2f9e-8da7-b45c5d5ee768@gmail.com>

On 03/29/2018 10:51 AM, Doug Berger wrote:
> On 03/27/2018 12:47 PM, Florian Fainelli wrote:
>> There were a number of issues with setting the RX coalescing parameters:
>>
>> - we would not be preserving values that would have been configured
>>   across close/open calls, instead we would always reset to no timeout
>>   and 1 interrupt per packet, this would also prevent DIM from setting its
>>   default usec/pkts values
>>
>> - when adaptive RX would be turned on, we woud not be fetching the
>>   default parameters, we would stay with no timeout/1 packet per interrupt
>>   until the estimator kicks in and changes that
>>
>> - finally disabling adaptive RX coalescing while providing parameters
>>   would not be honored, and we would stay with whatever DIM had previously
>>   determined instead of the user requested parameters
>>
>> Fixes: 9f4ca05827a2 ("net: bcmgenet: Add support for adaptive RX coalescing")
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>>  drivers/net/ethernet/broadcom/genet/bcmgenet.c | 78 ++++++++++++++++++--------
>>  drivers/net/ethernet/broadcom/genet/bcmgenet.h |  4 +-
>>  2 files changed, 57 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> index 7db8edc643ec..76409debb796 100644
>> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> @@ -625,18 +625,18 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
>>  	return 0;
>>  }
>>  
>> -static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring)
>> +static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring,
>> +				     u32 usecs, u32 pkts)
>>  {
>>  	struct bcmgenet_priv *priv = ring->priv;
>>  	unsigned int i = ring->index;
>>  	u32 reg;
>>  
>> -	bcmgenet_rdma_ring_writel(priv, i, ring->dim.coal_pkts,
>> -				  DMA_MBUF_DONE_THRESH);
>> +	bcmgenet_rdma_ring_writel(priv, i, pkts, DMA_MBUF_DONE_THRESH);
>>  
>>  	reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
>>  	reg &= ~DMA_TIMEOUT_MASK;
>> -	reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192);
>> +	reg |= DIV_ROUND_UP(usecs * 1000, 8192);
>>  	bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
>>  }
>>  
>> @@ -645,6 +645,8 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
>>  {
>>  	struct bcmgenet_priv *priv = netdev_priv(dev);
>>  	struct bcmgenet_rx_ring *ring;
>> +	struct net_dim_cq_moder moder;
>> +	u32 usecs, pkts;
>>  	unsigned int i;
>>  
>>  	/* Base system clock is 125Mhz, DMA timeout is this reference clock
>> @@ -682,25 +684,37 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
>>  
>>  	for (i = 0; i < priv->hw_params->rx_queues; i++) {
>>  		ring = &priv->rx_rings[i];
>> -		ring->dim.coal_usecs = ec->rx_coalesce_usecs;
>> -		ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
>> -		if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
>> -			ring->dim.coal_pkts = 1;
>> -			ring->dim.coal_usecs = 0;
>> +
>> +		ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
>> +		ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
>> +		usecs = ring->rx_coalesce_usecs;
>> +		pkts = ring->rx_max_coalesced_frames;
>> +
>> +		if (ec->use_adaptive_rx_coalesce) {
>> +			moder = net_dim_get_def_profile(ring->dim.dim.mode);
>> +			usecs = moder.usec;
>> +			pkts = moder.pkts;
>>  		}
>> +
>>  		ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
>> -		bcmgenet_set_rx_coalesce(ring);
>> +		bcmgenet_set_rx_coalesce(ring, usecs, pkts);
> You might want to put this loop code in a separate function with ring
> and ec parameters
> 
>>  	}
>>  
>>  	ring = &priv->rx_rings[DESC_INDEX];
>> -	ring->dim.coal_usecs = ec->rx_coalesce_usecs;
>> -	ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
>> -	if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
>> -		ring->dim.coal_pkts = 1;
>> -		ring->dim.coal_usecs = 0;
>> +
>> +	ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
>> +	ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
>> +	usecs = ring->rx_coalesce_usecs;
>> +	pkts = ring->rx_max_coalesced_frames;
>> +
>> +	if (ec->use_adaptive_rx_coalesce) {
>> +		moder = net_dim_get_def_profile(ring->dim.dim.mode);
>> +		usecs = moder.usec;
>> +		pkts = moder.pkts;
>>  	}
>> +
>>  	ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
>> -	bcmgenet_set_rx_coalesce(ring);
>> +	bcmgenet_set_rx_coalesce(ring, usecs, pkts);
> so you don't need to repeat it here. (just for maintenance reasons)
Looks like you already did in V2 :)!

I should read my mail more frequently ;).

> 
>>  
>>  	return 0;
>>  }
>> @@ -1924,10 +1938,7 @@ static void bcmgenet_dim_work(struct work_struct *work)
>>  	struct net_dim_cq_moder cur_profile =
>>  			net_dim_get_profile(dim->mode, dim->profile_ix);
>>  
>> -	ring->dim.coal_usecs = cur_profile.usec;
>> -	ring->dim.coal_pkts = cur_profile.pkts;
>> -
>> -	bcmgenet_set_rx_coalesce(ring);
>> +	bcmgenet_set_rx_coalesce(ring, cur_profile.usec, cur_profile.pkts);
>>  	dim->state = NET_DIM_START_MEASURE;
>>  }
>>  
>> @@ -2079,14 +2090,30 @@ static void init_umac(struct bcmgenet_priv *priv)
>>  	dev_dbg(kdev, "done init umac\n");
>>  }
>>  
>> -static void bcmgenet_init_dim(struct bcmgenet_net_dim *dim,
>> +static void bcmgenet_init_dim(struct bcmgenet_rx_ring *ring,
>>  			      void (*cb)(struct work_struct *work))
>>  {
>> +	struct bcmgenet_net_dim *dim = &ring->dim;
>> +	struct net_dim_cq_moder moder;
>> +	u32 usecs, pkts;
>> +
>>  	INIT_WORK(&dim->dim.work, cb);
>>  	dim->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
>>  	dim->event_ctr = 0;
>>  	dim->packets = 0;
>>  	dim->bytes = 0;
>> +
>> +	usecs = ring->rx_coalesce_usecs;
>> +	pkts = ring->rx_max_coalesced_frames;
>> +
>> +	/* If DIM was enabled, re-apply default parameters */
>> +	if (dim->use_dim) {
>> +		moder = net_dim_get_def_profile(dim->dim.mode);
>> +		usecs = moder.usec;
>> +		pkts = moder.pkts;
>> +	}
>> +
>> +	bcmgenet_set_rx_coalesce(ring, usecs, pkts);
>>  }
>>  
>>  /* Initialize a Tx ring along with corresponding hardware registers */
>> @@ -2178,7 +2205,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
>>  	if (ret)
>>  		return ret;
>>  
>> -	bcmgenet_init_dim(&ring->dim, bcmgenet_dim_work);
>> +	bcmgenet_init_dim(ring, bcmgenet_dim_work);
>>  
>>  	/* Initialize Rx NAPI */
>>  	netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll,
>> @@ -2186,7 +2213,6 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
>>  
>>  	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
>>  	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
>> -	bcmgenet_rdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
>>  	bcmgenet_rdma_ring_writel(priv, index,
>>  				  ((size << DMA_RING_SIZE_SHIFT) |
>>  				   RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
>> @@ -3424,6 +3450,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
>>  	struct net_device *dev;
>>  	const void *macaddr;
>>  	struct resource *r;
>> +	unsigned int i;
>>  	int err = -EIO;
>>  	const char *phy_mode_str;
>>  
>> @@ -3552,6 +3579,11 @@ static int bcmgenet_probe(struct platform_device *pdev)
>>  	netif_set_real_num_tx_queues(priv->dev, priv->hw_params->tx_queues + 1);
>>  	netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
>>  
>> +	/* Set default coalescing parameters */
>> +	for (i = 0; i < priv->hw_params->rx_queues; i++)
>> +		priv->rx_rings[i].rx_max_coalesced_frames = 1;
>> +	priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
>> +
>>  	/* libphy will determine the link state */
>>  	netif_carrier_off(dev);
>>  
>> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
>> index 22c41e0430fb..b773bc07edf7 100644
>> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
>> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
>> @@ -578,8 +578,6 @@ struct bcmgenet_net_dim {
>>  	u16		event_ctr;
>>  	unsigned long	packets;
>>  	unsigned long	bytes;
>> -	u32		coal_usecs;
>> -	u32		coal_pkts;
>>  	struct net_dim	dim;
>>  };
>>  
>> @@ -598,6 +596,8 @@ struct bcmgenet_rx_ring {
>>  	unsigned int	end_ptr;	/* Rx ring end CB ptr */
>>  	unsigned int	old_discards;
>>  	struct bcmgenet_net_dim dim;
>> +	u32		rx_max_coalesced_frames;
>> +	u32		rx_coalesce_usecs;
>>  	void (*int_enable)(struct bcmgenet_rx_ring *);
>>  	void (*int_disable)(struct bcmgenet_rx_ring *);
>>  	struct bcmgenet_priv *priv;
>>
> 

^ permalink raw reply

* Re: [iproute2-next 0/2] tipc: changes to addressing structure
From: David Ahern @ 2018-03-29 17:52 UTC (permalink / raw)
  To: Jon Maloy, davem, netdev
  Cc: mohan.krishna.ghanta.krishnamurthy, tung.q.nguyen, hoang.h.le,
	canh.d.luu, ying.xue, tipc-discussion
In-Reply-To: <1522255934-497-1-git-send-email-jon.maloy@ericsson.com>

On 3/28/18 10:52 AM, Jon Maloy wrote:
> 1: We introduce ability to set/get 128-bit node identities
> 2: We rename 'net id' to 'cluster id' in the command API, 
>    of course in a compatible way.
> 3: We print out all 32-bit node addresses as an integer in hex format,
>    i.e., we remove the assumption about an internal structure.
> 

Applied to iproute2-next. Thanks,

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: bcmgenet: Fix coalescing settings handling
From: Doug Berger @ 2018-03-29 17:51 UTC (permalink / raw)
  To: Florian Fainelli, netdev
  Cc: davem, jaedon.shin, pgynther, Michael Chan, gospo, talgi, saeedm
In-Reply-To: <20180327194707.31857-4-f.fainelli@gmail.com>

On 03/27/2018 12:47 PM, Florian Fainelli wrote:
> There were a number of issues with setting the RX coalescing parameters:
> 
> - we would not be preserving values that would have been configured
>   across close/open calls, instead we would always reset to no timeout
>   and 1 interrupt per packet, this would also prevent DIM from setting its
>   default usec/pkts values
> 
> - when adaptive RX would be turned on, we woud not be fetching the
>   default parameters, we would stay with no timeout/1 packet per interrupt
>   until the estimator kicks in and changes that
> 
> - finally disabling adaptive RX coalescing while providing parameters
>   would not be honored, and we would stay with whatever DIM had previously
>   determined instead of the user requested parameters
> 
> Fixes: 9f4ca05827a2 ("net: bcmgenet: Add support for adaptive RX coalescing")
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
>  drivers/net/ethernet/broadcom/genet/bcmgenet.c | 78 ++++++++++++++++++--------
>  drivers/net/ethernet/broadcom/genet/bcmgenet.h |  4 +-
>  2 files changed, 57 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index 7db8edc643ec..76409debb796 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -625,18 +625,18 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
>  	return 0;
>  }
>  
> -static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring)
> +static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring,
> +				     u32 usecs, u32 pkts)
>  {
>  	struct bcmgenet_priv *priv = ring->priv;
>  	unsigned int i = ring->index;
>  	u32 reg;
>  
> -	bcmgenet_rdma_ring_writel(priv, i, ring->dim.coal_pkts,
> -				  DMA_MBUF_DONE_THRESH);
> +	bcmgenet_rdma_ring_writel(priv, i, pkts, DMA_MBUF_DONE_THRESH);
>  
>  	reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
>  	reg &= ~DMA_TIMEOUT_MASK;
> -	reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192);
> +	reg |= DIV_ROUND_UP(usecs * 1000, 8192);
>  	bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
>  }
>  
> @@ -645,6 +645,8 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
>  {
>  	struct bcmgenet_priv *priv = netdev_priv(dev);
>  	struct bcmgenet_rx_ring *ring;
> +	struct net_dim_cq_moder moder;
> +	u32 usecs, pkts;
>  	unsigned int i;
>  
>  	/* Base system clock is 125Mhz, DMA timeout is this reference clock
> @@ -682,25 +684,37 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
>  
>  	for (i = 0; i < priv->hw_params->rx_queues; i++) {
>  		ring = &priv->rx_rings[i];
> -		ring->dim.coal_usecs = ec->rx_coalesce_usecs;
> -		ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
> -		if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
> -			ring->dim.coal_pkts = 1;
> -			ring->dim.coal_usecs = 0;
> +
> +		ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
> +		ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
> +		usecs = ring->rx_coalesce_usecs;
> +		pkts = ring->rx_max_coalesced_frames;
> +
> +		if (ec->use_adaptive_rx_coalesce) {
> +			moder = net_dim_get_def_profile(ring->dim.dim.mode);
> +			usecs = moder.usec;
> +			pkts = moder.pkts;
>  		}
> +
>  		ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
> -		bcmgenet_set_rx_coalesce(ring);
> +		bcmgenet_set_rx_coalesce(ring, usecs, pkts);
You might want to put this loop code in a separate function with ring
and ec parameters

>  	}
>  
>  	ring = &priv->rx_rings[DESC_INDEX];
> -	ring->dim.coal_usecs = ec->rx_coalesce_usecs;
> -	ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
> -	if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
> -		ring->dim.coal_pkts = 1;
> -		ring->dim.coal_usecs = 0;
> +
> +	ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
> +	ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
> +	usecs = ring->rx_coalesce_usecs;
> +	pkts = ring->rx_max_coalesced_frames;
> +
> +	if (ec->use_adaptive_rx_coalesce) {
> +		moder = net_dim_get_def_profile(ring->dim.dim.mode);
> +		usecs = moder.usec;
> +		pkts = moder.pkts;
>  	}
> +
>  	ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
> -	bcmgenet_set_rx_coalesce(ring);
> +	bcmgenet_set_rx_coalesce(ring, usecs, pkts);
so you don't need to repeat it here. (just for maintenance reasons)

>  
>  	return 0;
>  }
> @@ -1924,10 +1938,7 @@ static void bcmgenet_dim_work(struct work_struct *work)
>  	struct net_dim_cq_moder cur_profile =
>  			net_dim_get_profile(dim->mode, dim->profile_ix);
>  
> -	ring->dim.coal_usecs = cur_profile.usec;
> -	ring->dim.coal_pkts = cur_profile.pkts;
> -
> -	bcmgenet_set_rx_coalesce(ring);
> +	bcmgenet_set_rx_coalesce(ring, cur_profile.usec, cur_profile.pkts);
>  	dim->state = NET_DIM_START_MEASURE;
>  }
>  
> @@ -2079,14 +2090,30 @@ static void init_umac(struct bcmgenet_priv *priv)
>  	dev_dbg(kdev, "done init umac\n");
>  }
>  
> -static void bcmgenet_init_dim(struct bcmgenet_net_dim *dim,
> +static void bcmgenet_init_dim(struct bcmgenet_rx_ring *ring,
>  			      void (*cb)(struct work_struct *work))
>  {
> +	struct bcmgenet_net_dim *dim = &ring->dim;
> +	struct net_dim_cq_moder moder;
> +	u32 usecs, pkts;
> +
>  	INIT_WORK(&dim->dim.work, cb);
>  	dim->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
>  	dim->event_ctr = 0;
>  	dim->packets = 0;
>  	dim->bytes = 0;
> +
> +	usecs = ring->rx_coalesce_usecs;
> +	pkts = ring->rx_max_coalesced_frames;
> +
> +	/* If DIM was enabled, re-apply default parameters */
> +	if (dim->use_dim) {
> +		moder = net_dim_get_def_profile(dim->dim.mode);
> +		usecs = moder.usec;
> +		pkts = moder.pkts;
> +	}
> +
> +	bcmgenet_set_rx_coalesce(ring, usecs, pkts);
>  }
>  
>  /* Initialize a Tx ring along with corresponding hardware registers */
> @@ -2178,7 +2205,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
>  	if (ret)
>  		return ret;
>  
> -	bcmgenet_init_dim(&ring->dim, bcmgenet_dim_work);
> +	bcmgenet_init_dim(ring, bcmgenet_dim_work);
>  
>  	/* Initialize Rx NAPI */
>  	netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll,
> @@ -2186,7 +2213,6 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
>  
>  	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
>  	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
> -	bcmgenet_rdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
>  	bcmgenet_rdma_ring_writel(priv, index,
>  				  ((size << DMA_RING_SIZE_SHIFT) |
>  				   RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
> @@ -3424,6 +3450,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
>  	struct net_device *dev;
>  	const void *macaddr;
>  	struct resource *r;
> +	unsigned int i;
>  	int err = -EIO;
>  	const char *phy_mode_str;
>  
> @@ -3552,6 +3579,11 @@ static int bcmgenet_probe(struct platform_device *pdev)
>  	netif_set_real_num_tx_queues(priv->dev, priv->hw_params->tx_queues + 1);
>  	netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
>  
> +	/* Set default coalescing parameters */
> +	for (i = 0; i < priv->hw_params->rx_queues; i++)
> +		priv->rx_rings[i].rx_max_coalesced_frames = 1;
> +	priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
> +
>  	/* libphy will determine the link state */
>  	netif_carrier_off(dev);
>  
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> index 22c41e0430fb..b773bc07edf7 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> @@ -578,8 +578,6 @@ struct bcmgenet_net_dim {
>  	u16		event_ctr;
>  	unsigned long	packets;
>  	unsigned long	bytes;
> -	u32		coal_usecs;
> -	u32		coal_pkts;
>  	struct net_dim	dim;
>  };
>  
> @@ -598,6 +596,8 @@ struct bcmgenet_rx_ring {
>  	unsigned int	end_ptr;	/* Rx ring end CB ptr */
>  	unsigned int	old_discards;
>  	struct bcmgenet_net_dim dim;
> +	u32		rx_max_coalesced_frames;
> +	u32		rx_coalesce_usecs;
>  	void (*int_enable)(struct bcmgenet_rx_ring *);
>  	void (*int_disable)(struct bcmgenet_rx_ring *);
>  	struct bcmgenet_priv *priv;
> 

^ permalink raw reply

* Re: [PATCH net-next 0/5] Introduce net_rwsem to protect net_namespace_list
From: David Miller @ 2018-03-29 17:48 UTC (permalink / raw)
  To: ktkhai-5HdwGun5lf+gSpxsJD1C4w
  Cc: jakub.kicinski-wFxRvT7yatFl57MIdRCFDg,
	avagin-5HdwGun5lf+gSpxsJD1C4w,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	linux-qQsb+v5E8BnlAoU/VqSP6n9LOBIZ5rWg,
	ast-DgEjT+Ai2ygdnm+yROfE0A, roman.kapl-uSbOeAmDUekAvxtiuMwx3w,
	selinux-+05T5uksL2qpZYMLLGbcSA,
	christian.brauner-GeWIH/nMZzLQT0dZR+AlfA,
	dev-yBygre7rU0TnMu66kgdUjQ,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	lucien.xin-Re5JQEeQqe8AvxtiuMwx3w, paul-r2n+y4ga6xFZroRs9YW3xA,
	leon-DgEjT+Ai2ygdnm+yROfE0A, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	jmorris-gx6/JNMH7DfYtjvyW6yDsg, jgg-uk2M96/98Pc,
	dledford-H+wXaHxf7aLQT0dZR+AlfA, coreteam-Cap9r6Oaw4JrovVCs/uTlw,
	kadlec-K40Dz/62t/MgiyqX0sVFJYdd74u8MsAO,
	paulmck-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8,
	sds-+05T5uksL2qpZYMLLGbcSA, pablo-Cap9r6Oaw4JrovVCs/uTlw,
	serge-A9i7LUbDfNHQT0dZR+AlfA, parav-VPRAkNaXOzVWk0Htik3J/w,
	brouer-H+wXaHxf7aLQT0dZR+AlfA, yuval.shaia-QHcLZuEGTsvQT0dZR+AlfA,
	jbenc-H+wXaHxf7aLQT0dZR+AlfA, idosch-VPRAkNaXOzVWk0Htik3J/w,
	jiri-VPRAkNaXOzVWk0Htik3J/w, eparis-FjpueFixGhCM4zKIHC2jIg,
	nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, vvs-5HdwGun5lf+gSpxsJD1C4w,
	daniel-FeC+5ew28dpmcu3hnIyYJQ, pombredanne-od1rfyK75/E,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	vyasevich-Re5JQEeQqe8AvxtiuMwx3w, fw-HFFVJYpyMKqzQB+pC5nmwQ,
	danielj-VPRAkNaXOzVWk0Htik3J/w, ma
In-Reply-To: <152234005959.19153.17907173734141707348.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

From: Kirill Tkhai <ktkhai-5HdwGun5lf+gSpxsJD1C4w@public.gmane.org>
Date: Thu, 29 Mar 2018 19:20:23 +0300

> The series introduces fine grained rw_semaphore, which will be used
> instead of rtnl_lock() to protect net_namespace_list.
> 
> This improves scalability and allows to do non-exclusive sleepable
> iteration for_each_net(), which is enough for most cases.
> 
> scripts/get_maintainer.pl gives enormous list of people, and I add
> all to CC.
> 
> Note, that this patch is independent of "Close race between
> {un, }register_netdevice_notifier and pernet_operations":
> https://patchwork.ozlabs.org/project/netdev/list/?series=36495
> 
> Signed-off-by: Kirill Tkhai <ktkhai-5HdwGun5lf+gSpxsJD1C4w@public.gmane.org>

Great stuff!

Series applied, thanks!

^ permalink raw reply

* Re: [PATCH bpf-next RFC 2/2] Add MPLS label push/pop functions for EBPF
From: Shrijeet mukherjee @ 2018-03-29 17:35 UTC (permalink / raw)
  To: David Ahern; +Cc: daniel, netdev, roopa, ast
In-Reply-To: <6f22e464-21a4-1d1e-7412-080e03328f6c@cumulusnetworks.com>

On 03/28, David Ahern wrote:
> On 3/28/18 10:27 AM, Shrijeet Mukherjee wrote:
> 
> > +static int bpf_skb_mpls_net_grow(struct sk_buff *skb, int len_diff)
> > +{
> > +	u32 off = skb_mac_header_len(skb); /*LL_RESERVED_SPACE ?? */
> > +	int ret;
> > +
> > +	ret = skb_cow(skb, len_diff);
> > +	if (unlikely(ret < 0))
> > +		return ret;
> > +
> > +	skb_set_inner_protocol(skb, skb->protocol);
> > +	skb_reset_inner_network_header(skb);
> > +
> > +	ret = bpf_skb_generic_push(skb, off, len_diff);
> > +	if (unlikely(ret < 0))
> > +		return ret;
> > +
> > +	skb_reset_mac_header(skb);
> > +	skb_set_network_header(skb, ETH_HLEN);
> > +	skb->protocol = eth_hdr(skb)->h_proto = htons(ETH_P_MPLS_UC);
> > +
> > +	if (skb_is_gso(skb)) {
> > +/* Due to header grow, MSS needs to be downgraded. */
> > +		skb_shinfo(skb)->gso_size -= len_diff;
> > +/* Header must be checked, and gso_segs recomputed. */
> > +		skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
> > +		skb_shinfo(skb)->gso_segs = 0;
> > +	}
> > +
> > +	bpf_compute_data_pointers(skb);
> > +	return 0;
> > +}
> 
> The only thing MPLS specific is the protocol setting. Seems to me you
> could leverage the existing bpf_skb_net_grow or even bpf_skb_adjust_net
> and then set the protocols and headers in the caller of this function.
> You already do something similar in bpf_skb_mpls_pop.
> 

At a high level, this is the discussion I want to have. There is a loss of efficiency if we try to make generic functions and there are differences which are subtle as MPLS does not have an encompassing header. So, do we want the filter functions to become more common (and I can generate a patch to that point) or do we want them to be hyper-efficient is the question I am seeking an answer to.

Will address all the other comments in v2
> 
> > +
> > +BPF_CALL_2(bpf_skb_mpls_pop, struct sk_buff*, skb, u32, num_lbls)
> > +{
> > +	u32 i = 0;
> > +	struct mpls_shim_hdr *hdr;
> > +	unsigned char *cursor;
> > +	struct mpls_entry_decoded dec;
> > +
> > +	if (num_lbls == 0)
> > +		return 0;
> > +
> > +	cursor = skb_network_header(skb);
> > +	do {
> > +		hdr = (struct mpls_shim_hdr *)cursor;
> > +		dec = mpls_entry_decode(hdr);
> > +		i++; cursor = cursor + sizeof(struct mpls_shim_hdr);
> > +	} while (dec.bos != 1 && i < num_lbls);
> > +
> > +	bpf_push_mac_rcsum(skb);
> > +	skb_pull(skb, i * sizeof(struct mpls_shim_hdr));
> > +	skb_reset_network_header(skb);
> > +
> > +	skb->protocol = eth_hdr(skb)->h_proto = htons(ETH_P_MPLS_UC);
> 
> If I pop 1 label and there are more of them, then the protocol does not
> need to be adjusted -- it was already set to MPLS.
> 
> If I pop all of the labels, then the protocol is not MPLS, but whatever
> the inner packet is -- IPv4 or IPv6 or other.

This is the other real question. The filter functions do not allow a generic array to be returned, so the current expectation is that the callee has parsed the full MPLS label stack and provides the correct number. This could mean that MPLS pop is just a generic reduce_hdr_by function and the protocol etc is handled by the bpf program. I don't like that as it will mean incoherent protocol handling in bpf programs. But wanted to hear opinions.

> 
> 
> > +	bpf_pull_mac_rcsum(skb);
> > +	bpf_compute_data_pointers(skb);
> > +
> > +	return i;
> > +}
> > +
> > +const struct bpf_func_proto bpf_skb_mpls_pop_proto = {
> > +				.func   = bpf_skb_mpls_pop,
> > +				.gpl_only = false,
> > +				.ret_type = RET_INTEGER,
> > +				.arg1_type  = ARG_PTR_TO_CTX,
> > +				.arg2_type  = ARG_ANYTHING,
> > +};
> > +EXPORT_SYMBOL_GPL(bpf_skb_mpls_pop_proto);
> > +
> > +BPF_CALL_3(bpf_skb_mpls_push, struct sk_buff*, skb,
> > +	   __be32*, lbls, u32, num_lbls)
> > +{
> > +	int ret, i;
> > +	unsigned int new_header_size = num_lbls * sizeof(__be32);
> > +	unsigned int ttl = 255;
> > +	struct dst_entry *dst = skb_dst(skb);
> 
> dst is not always set. e.g., any program on ingress prior to the layer 3
> will not have it.
> 
> 
> > +	struct net_device *out_dev = dst->dev;
> > +	struct mpls_shim_hdr *hdr;
> > +	bool bos;
> > +
> > +	/* Ensure there is enough space for the headers in the skb */
> > +	ret = bpf_skb_mpls_net_grow(skb, new_header_size);
> > +	if (ret < 0) {
> > +		trace_printk("COW was killed\n");
> > +		bpf_compute_data_pointers(skb);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	skb->dev = out_dev;
> > +/* XXX this may need finesse to integrate with
> > + * global TTL values for MPLS
> > + */
> > +	if (dst->ops->family == AF_INET)
> > +		ttl = ip_hdr(skb)->ttl;
> > +	else if (dst->ops->family == AF_INET6)
> > +		ttl = ipv6_hdr(skb)->hop_limit;
> > +
> > +	/* Push the new labels */
> > +	hdr = skb_mpls_hdr(skb);
> > +	bos = true;
> > +	for (i = num_lbls - 1; i >= 0; i--) {
> > +		hdr[i] = mpls_entry_encode(lbls[i], ttl, 0, bos);
> > +		bos = false;
> > +	}
> > +
> > +	bpf_compute_data_pointers(skb);
> > +	return 0;
> > +}
> > +
> > +const struct bpf_func_proto bpf_skb_mpls_push_proto = {
> > +	.func		= bpf_skb_mpls_push,
> > +	.gpl_only	= false,
> > +	.ret_type	= RET_INTEGER,
> > +	.arg1_type	= ARG_PTR_TO_CTX,
> > +	.arg2_type	= ARG_PTR_TO_MEM,
> > +	.arg3_type	= ARG_CONST_SIZE,
> > +};
> > +EXPORT_SYMBOL_GPL(bpf_skb_mpls_push_proto);
> > +
> >  static u32 __bpf_skb_min_len(const struct sk_buff *skb)
> >  {
> >  	u32 min_len = skb_network_offset(skb);
> > @@ -3019,6 +3138,8 @@ bool bpf_helper_changes_pkt_data(void *func)
> >  {
> >  	if (func == bpf_skb_vlan_push ||
> >  	    func == bpf_skb_vlan_pop ||
> > +	    func == bpf_skb_mpls_push ||
> > +	    func == bpf_skb_mpls_pop ||
> >  	    func == bpf_skb_store_bytes ||
> >  	    func == bpf_skb_change_proto ||
> >  	    func == bpf_skb_change_head ||
> > @@ -3682,6 +3803,10 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
> >  		return &bpf_skb_vlan_push_proto;
> >  	case BPF_FUNC_skb_vlan_pop:
> >  		return &bpf_skb_vlan_pop_proto;
> > +	case BPF_FUNC_skb_mpls_push:
> > +		return &bpf_skb_mpls_push_proto;
> > +	case BPF_FUNC_skb_mpls_pop:
> > +		return &bpf_skb_mpls_pop_proto;
> >  	case BPF_FUNC_skb_change_proto:
> >  		return &bpf_skb_change_proto_proto;
> >  	case BPF_FUNC_skb_change_type:
> > 
> 

^ permalink raw reply

* [PATCH net v3 3/3] ipv6: udp6: set dst cache for a connected sk if current not valid
From: Alexey Kodanev @ 2018-03-29 17:37 UTC (permalink / raw)
  To: netdev; +Cc: Eric Dumazet, Martin KaFai Lau, David Miller, Alexey Kodanev
In-Reply-To: <1522345042-26646-1-git-send-email-alexey.kodanev@oracle.com>

A new RTF_CACHE route can be created in udpv6_sendmsg() between
ip6_sk_dst_lookup_flow() and ip6_dst_store() calls when datagram
sending results to ICMPV6_PKT_TOOBIG error:

    udp_v6_send_skb(), for example with vti6 tunnel:
        vti6_xmit(), get ICMPV6_PKT_TOOBIG error
            skb_dst_update_pmtu(), can create a RTF_CACHE clone
            icmpv6_send()
    ...
    udpv6_err()
        ip6_sk_update_pmtu()
           ip6_update_pmtu(), can create a RTF_CACHE clone
           ...
           ip6_datagram_dst_update()
                ip6_dst_store()

And after commit 33c162a980fe ("ipv6: datagram: Update dst cache
of a connected datagram sk during pmtu update"), the UDPv6 error
handler can update socket's dst cache, but it can happen before
the update in end of udpv6_sendmsg(), preventing getting updated
dst cache on the next udpv6_sendmsg() calls.

In order to fix it, we should save dst for a connected socket
in udpv6_sendmsg(), only if the previous socket's cache is not
valid.

Fixes: 33c162a980fe ("ipv6: datagram: Update dst cache of a connected datagram sk during pmtu update")
Fixes: 45e4fd26683c ("ipv6: Only create RTF_CACHE routes after encountering pmtu exception")
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 net/ipv6/udp.c | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e49dac4..da13c90 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1289,7 +1289,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
 	fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
 
-	dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, 0);
+	dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, connected);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		dst = NULL;
@@ -1314,7 +1314,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 		err = PTR_ERR(skb);
 		if (!IS_ERR_OR_NULL(skb))
 			err = udp_v6_send_skb(skb, &fl6);
-		goto release_dst;
+		goto out;
 	}
 
 	lock_sock(sk);
@@ -1348,23 +1348,6 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 		err = np->recverr ? net_xmit_errno(err) : 0;
 	release_sock(sk);
 
-release_dst:
-	if (dst) {
-		if (connected) {
-			ip6_dst_store(sk, dst,
-				      ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
-				      &sk->sk_v6_daddr : NULL,
-#ifdef CONFIG_IPV6_SUBTREES
-				      ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
-				      &np->saddr :
-#endif
-				      NULL);
-		} else {
-			dst_release(dst);
-		}
-		dst = NULL;
-	}
-
 out:
 	dst_release(dst);
 	fl6_sock_release(flowlabel);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net v3 1/3] ipv6: move ip6_dst_store() calls with flowi6 checks to a wrapper
From: Alexey Kodanev @ 2018-03-29 17:37 UTC (permalink / raw)
  To: netdev; +Cc: Eric Dumazet, Martin KaFai Lau, David Miller, Alexey Kodanev
In-Reply-To: <1522345042-26646-1-git-send-email-alexey.kodanev@oracle.com>

Move commonly used pattern of ip6_dst_store() usage to a separate
function - ip6_dst_store_flow(), which will check the addresses
for equality before saving them.

There is no functional changes in this patch, the new wrapper
will be used in the next patch, in ip6_sk_dst_lookup_flow().

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 include/net/ip6_route.h | 17 +++++++++++++++++
 net/ipv6/datagram.c     |  9 +--------
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index ac0866b..36c3946 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -210,6 +210,23 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
 #endif
 }
 
+static inline void ip6_dst_store_flow(struct sock *sk, struct dst_entry *dst,
+				      struct flowi6 *fl6)
+{
+#ifdef CONFIG_IPV6_SUBTREES
+	struct ipv6_pinfo *np = inet6_sk(sk);
+#endif
+
+	ip6_dst_store(sk, dst,
+		      ipv6_addr_equal(&fl6->daddr, &sk->sk_v6_daddr) ?
+		      &sk->sk_v6_daddr : NULL,
+#ifdef CONFIG_IPV6_SUBTREES
+		      ipv6_addr_equal(&fl6->saddr, &np->saddr) ?
+		      &np->saddr :
+#endif
+		      NULL);
+}
+
 static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
 {
 	struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a9f7eca..8b4fa0c 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -106,14 +106,7 @@ int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr)
 		}
 	}
 
-	ip6_dst_store(sk, dst,
-		      ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
-		      &sk->sk_v6_daddr : NULL,
-#ifdef CONFIG_IPV6_SUBTREES
-		      ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
-		      &np->saddr :
-#endif
-		      NULL);
+	ip6_dst_store_flow(sk, dst, &fl6);
 
 out:
 	fl6_sock_release(flowlabel);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net v3 2/3] ipv6: allow to cache dst for connected sk in ip6_sk_dst_lookup_flow()
From: Alexey Kodanev @ 2018-03-29 17:37 UTC (permalink / raw)
  To: netdev; +Cc: Eric Dumazet, Martin KaFai Lau, David Miller, Alexey Kodanev
In-Reply-To: <1522345042-26646-1-git-send-email-alexey.kodanev@oracle.com>

Add 'connected' argument to ip6_sk_dst_lookup_flow() and
update the cache only if ip6_sk_dst_check() returns NULL
and a socket is connected.

The function is used as before, the new behavior for UDP
sockets in udpv6_sendmsg() will be enabled in the next
patch.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 include/net/ipv6.h    |  3 ++-
 net/ipv6/ip6_output.c | 15 ++++++++++++---
 net/ipv6/ping.c       |  2 +-
 net/ipv6/udp.c        |  2 +-
 4 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 8606c91..07e94dc 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -977,7 +977,8 @@ int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst,
 struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
 				      const struct in6_addr *final_dst);
 struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
-					 const struct in6_addr *final_dst);
+					 const struct in6_addr *final_dst,
+					 int connected);
 struct dst_entry *ip6_blackhole_route(struct net *net,
 				      struct dst_entry *orig_dst);
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a8a9195..c22017c 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1105,23 +1105,32 @@ struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
  *	@sk: socket which provides the dst cache and route info
  *	@fl6: flow to lookup
  *	@final_dst: final destination address for ipsec lookup
+ *	@connected: whether @sk is connected or not
  *
  *	This function performs a route lookup on the given flow with the
  *	possibility of using the cached route in the socket if it is valid.
  *	It will take the socket dst lock when operating on the dst cache.
  *	As a result, this function can only be used in process context.
  *
+ *	In addition, for a connected socket, cache the dst in the socket
+ *	if the current cache is not valid.
+ *
  *	It returns a valid dst pointer on success, or a pointer encoded
  *	error code.
  */
 struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
-					 const struct in6_addr *final_dst)
+					 const struct in6_addr *final_dst,
+					 int connected)
 {
 	struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
 
 	dst = ip6_sk_dst_check(sk, dst, fl6);
-	if (!dst)
-		dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
+	if (dst)
+		return dst;
+
+	dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
+	if (connected && !IS_ERR(dst))
+		ip6_dst_store_flow(sk, dst_clone(dst), fl6);
 
 	return dst;
 }
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index d12c55d..546f4a6 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -121,7 +121,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 	ipc6.tclass = np->tclass;
 	fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
 
-	dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr);
+	dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 0);
 	if (IS_ERR(dst))
 		return PTR_ERR(dst);
 	rt = (struct rt6_info *) dst;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 52e3ea0..e49dac4 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1289,7 +1289,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
 	fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
 
-	dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, 0);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		dst = NULL;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net v3 0/3] ipv6: udp6: set dst cache for a connected sk if current not valid
From: Alexey Kodanev @ 2018-03-29 17:37 UTC (permalink / raw)
  To: netdev; +Cc: Eric Dumazet, Martin KaFai Lau, David Miller, Alexey Kodanev

A new RTF_CACHE route can be created with the socket's dst cache
update between the below calls in udpv6_sendmsg(), when datagram
sending results to ICMPV6_PKT_TOOBIG error:

   dst = ip6_sk_dst_lookup_flow(...)
   ...
release_dst:
    if (dst) {
        if (connected)
            ip6_dst_store(sk, dst)

Therefore, the new socket's dst cache reset to the old one on
"release_dst:".

The first two patches prepare the code to store dst cache
with ip6_sk_dst_lookup_flow() in udpv6_sendmsg():

  * the first patch adds new wrapper ip6_dst_store_flow() to
    increase readability of the code and the changes.

  * the second patch adds new argument to ip6_sk_dst_lookup_flow()
    and ability to store dst in the socket's cache. Also, the two
    users of the function are updated without enabling the new
    behavior: pingv6_sendmsg() and udpv6_sendmsg().

The last patch contains the actual fix that removes sk dst cache
update in the end of udpv6_sendmsg(), and allows to do it in
ip6_sk_dst_lookup_flow().

v3: * instead of moving ip6_dst_store() above udp_v6_send_skb(),
      update socket's dst cache inside ip6_sk_dst_lookup_flow()
      if the current one is invalid.
    * the issue not reproduced in 4.1, but starting from 4.2. Add
      one more 'Fixes:' commit that creates new RTF_CACHE route.
      Though, it is also mentioned in the first one.

Alexey Kodanev (3):
  ipv6: move ip6_dst_store() calls with flowi6 checks to a wrapper
  ipv6: allow to cache dst for connected sk in ip6_sk_dst_lookup_flow()
  ipv6: udp6: set dst cache for a connected sk if current not valid

 include/net/ip6_route.h | 17 +++++++++++++++++
 include/net/ipv6.h      |  3 ++-
 net/ipv6/datagram.c     |  9 +--------
 net/ipv6/ip6_output.c   | 15 ++++++++++++---
 net/ipv6/ping.c         |  2 +-
 net/ipv6/udp.c          | 21 ++-------------------
 6 files changed, 35 insertions(+), 32 deletions(-)

-- 
1.8.3.1

^ permalink raw reply

* Re: [PATCH net-next 0/9] devlink: Add support for region access
From: Andrew Lunn @ 2018-03-29 17:13 UTC (permalink / raw)
  To: Alex Vesker; +Cc: David S. Miller, netdev, Tariq Toukan, Jiri Pirko
In-Reply-To: <1522339672-18273-1-git-send-email-valex@mellanox.com>

On Thu, Mar 29, 2018 at 07:07:43PM +0300, Alex Vesker wrote:
> This is a proposal which will allow access to driver defined address
> regions using devlink. Each device can create its supported address
> regions and register them. A device which exposes a region will allow
> access to it using devlink.
> 
> The suggested implementation will allow exposing regions to the user,
> reading and dumping snapshots taken from different regions. 
> A snapshot represents a memory image of a region taken by the driver.
> 
> If a device collects a snapshot of an address region it can be later
> exposed using devlink region read or dump commands.
> This functionality allows for future analyses on the snapshots to be
> done.

Hi Alex

So the device is in change of making a snapshot? A user cannot
initiate it?

Seems like if i'm trying to debug something, i want to take a snapshot
in the good state, issue the command which breaks things, and then
take another snapshot. Looking at the diff then gives me an idea what
happened.

> Show all of the exposed regions with region sizes:
> $ devlink region show
> pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]

So you have 2Mbytes of snapshot data. Is this held in the device, or
kernel memory?

> Dump a snapshot:
> $ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
> 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
> 0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8
> 0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc
> 0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5
> 
> Read a specific part of a snapshot:
> $ devlink region read pci/0000:00:05.0/fw-health snapshot 1 address 0 
> 	length 16
> 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30

Why a separate command? It seems to be just a subset of dump.

    Andrew

^ permalink raw reply

* Re: [PATCH v2 0/2] gfs2: Stop using rhashtable_walk_peek
From: Herbert Xu @ 2018-03-29 17:06 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: cluster-devel, netdev, LKML, NeilBrown, Thomas Graf, Tom Herbert
In-Reply-To: <CAHc6FU708-F-C_ihwBW-zKC7rZvfeuKYq7kTccZQU156UicjQA@mail.gmail.com>

On Thu, Mar 29, 2018 at 06:52:34PM +0200, Andreas Gruenbacher wrote:
>
> Should rhashtable_walk_peek be kept around even if there are no more
> users? I have my doubts.

Absolutely.  All netlink dumps using rhashtable_walk_next are buggy
and need to switch over to rhashtable_walk_peek.  As otherwise
the object that triggers the out-of-space condition will be skipped
upon resumption.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [net-next V7 PATCH 16/16] xdp: transition into using xdp_frame for ndo_xdp_xmit
From: Jesper Dangaard Brouer @ 2018-03-29 17:02 UTC (permalink / raw)
  To: netdev, BjörnTöpel, magnus.karlsson
  Cc: eugenia, Jason Wang, John Fastabend, Eran Ben Elisha,
	Saeed Mahameed, galp, Jesper Dangaard Brouer, Daniel Borkmann,
	Alexei Starovoitov, Tariq Toukan
In-Reply-To: <152234282394.17048.1345050519681161537.stgit@firesoul>

Changing API ndo_xdp_xmit to take a struct xdp_frame instead of struct
xdp_buff.  This brings xdp_return_frame and ndp_xdp_xmit in sync.

This builds towards changing the API further to become a bulk API,
because xdp_buff is not a queue-able object while xdp_frame is.

V4: Adjust for commit 59655a5b6c83 ("tuntap: XDP_TX can use native XDP")
V7: Adjust for commit d9314c474d4f ("i40e: add support for XDP_REDIRECT")

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |   30 ++++++++++++++-----------
 drivers/net/ethernet/intel/i40e/i40e_txrx.h   |    2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |   21 +++++++++---------
 drivers/net/tun.c                             |   19 ++++++++++------
 drivers/net/virtio_net.c                      |   24 ++++++++++++--------
 include/linux/netdevice.h                     |    4 ++-
 net/core/filter.c                             |   17 +++++++++++++-
 7 files changed, 72 insertions(+), 45 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index c8bf4d35fdea..87fb27ab9c24 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2203,9 +2203,20 @@ static bool i40e_is_non_eop(struct i40e_ring *rx_ring,
 #define I40E_XDP_CONSUMED 1
 #define I40E_XDP_TX 2
 
-static int i40e_xmit_xdp_ring(struct xdp_buff *xdp,
+static int i40e_xmit_xdp_ring(struct xdp_frame *xdpf,
 			      struct i40e_ring *xdp_ring);
 
+static int i40e_xmit_xdp_tx_ring(struct xdp_buff *xdp,
+				 struct i40e_ring *xdp_ring)
+{
+	struct xdp_frame *xdpf = convert_to_xdp_frame(xdp);
+
+	if (unlikely(!xdpf))
+		return I40E_XDP_CONSUMED;
+
+	return i40e_xmit_xdp_ring(xdpf, xdp_ring);
+}
+
 /**
  * i40e_run_xdp - run an XDP program
  * @rx_ring: Rx ring being processed
@@ -2233,7 +2244,7 @@ static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring,
 		break;
 	case XDP_TX:
 		xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
-		result = i40e_xmit_xdp_ring(xdp, xdp_ring);
+		result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
 		break;
 	case XDP_REDIRECT:
 		err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
@@ -3480,21 +3491,14 @@ static inline int i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
  * @xdp: data to transmit
  * @xdp_ring: XDP Tx ring
  **/
-static int i40e_xmit_xdp_ring(struct xdp_buff *xdp,
+static int i40e_xmit_xdp_ring(struct xdp_frame *xdpf,
 			      struct i40e_ring *xdp_ring)
 {
 	u16 i = xdp_ring->next_to_use;
 	struct i40e_tx_buffer *tx_bi;
 	struct i40e_tx_desc *tx_desc;
-	struct xdp_frame *xdpf;
+	u32 size = xdpf->len;
 	dma_addr_t dma;
-	u32 size;
-
-	xdpf = convert_to_xdp_frame(xdp);
-	if (unlikely(!xdpf))
-		return I40E_XDP_CONSUMED;
-
-	size = xdpf->len;
 
 	if (!unlikely(I40E_DESC_UNUSED(xdp_ring))) {
 		xdp_ring->tx_stats.tx_busy++;
@@ -3684,7 +3688,7 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
  *
  * Returns Zero if sent, else an error code
  **/
-int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
+int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
 {
 	struct i40e_netdev_priv *np = netdev_priv(dev);
 	unsigned int queue_index = smp_processor_id();
@@ -3697,7 +3701,7 @@ int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
 	if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
 		return -ENXIO;
 
-	err = i40e_xmit_xdp_ring(xdp, vsi->xdp_rings[queue_index]);
+	err = i40e_xmit_xdp_ring(xdpf, vsi->xdp_rings[queue_index]);
 	if (err != I40E_XDP_TX)
 		return -ENOSPC;
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index 857b1d743c8d..4bf318b8be85 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -511,7 +511,7 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw);
 void i40e_detect_recover_hung(struct i40e_vsi *vsi);
 int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
 bool __i40e_chk_linearize(struct sk_buff *skb);
-int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp);
+int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf);
 void i40e_xdp_flush(struct net_device *dev);
 
 /**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 4f2864165723..0daccaf72a30 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2262,7 +2262,7 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,
 #define IXGBE_XDP_TX 2
 
 static int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter,
-			       struct xdp_buff *xdp);
+			       struct xdp_frame *xdpf);
 
 static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
 				     struct ixgbe_ring *rx_ring,
@@ -2270,6 +2270,7 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
 {
 	int err, result = IXGBE_XDP_PASS;
 	struct bpf_prog *xdp_prog;
+	struct xdp_frame *xdpf;
 	u32 act;
 
 	rcu_read_lock();
@@ -2283,7 +2284,12 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
 	case XDP_PASS:
 		break;
 	case XDP_TX:
-		result = ixgbe_xmit_xdp_ring(adapter, xdp);
+		xdpf = convert_to_xdp_frame(xdp);
+		if (unlikely(!xdpf)) {
+			result = IXGBE_XDP_CONSUMED;
+			break;
+		}
+		result = ixgbe_xmit_xdp_ring(adapter, xdpf);
 		break;
 	case XDP_REDIRECT:
 		err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog);
@@ -8344,20 +8350,15 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
 }
 
 static int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter,
-			       struct xdp_buff *xdp)
+			       struct xdp_frame *xdpf)
 {
 	struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()];
 	struct ixgbe_tx_buffer *tx_buffer;
 	union ixgbe_adv_tx_desc *tx_desc;
-	struct xdp_frame *xdpf;
 	u32 len, cmd_type;
 	dma_addr_t dma;
 	u16 i;
 
-	xdpf = convert_to_xdp_frame(xdp);
-	if (unlikely(!xdpf))
-		return -EOVERFLOW;
-
 	len = xdpf->len;
 
 	if (unlikely(!ixgbe_desc_unused(ring)))
@@ -10010,7 +10011,7 @@ static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp)
 	}
 }
 
-static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
+static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 	struct ixgbe_ring *ring;
@@ -10026,7 +10027,7 @@ static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
 	if (unlikely(!ring))
 		return -ENXIO;
 
-	err = ixgbe_xmit_xdp_ring(adapter, xdp);
+	err = ixgbe_xmit_xdp_ring(adapter, xdpf);
 	if (err != IXGBE_XDP_TX)
 		return -ENOSPC;
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a6a74e896430..46ac5dd79fa3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1294,18 +1294,13 @@ static const struct net_device_ops tun_netdev_ops = {
 	.ndo_get_stats64	= tun_net_get_stats64,
 };
 
-static int tun_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
+static int tun_xdp_xmit(struct net_device *dev, struct xdp_frame *frame)
 {
 	struct tun_struct *tun = netdev_priv(dev);
-	struct xdp_frame *frame;
 	struct tun_file *tfile;
 	u32 numqueues;
 	int ret = 0;
 
-	frame = convert_to_xdp_frame(xdp);
-	if (unlikely(!frame))
-		return -EOVERFLOW;
-
 	rcu_read_lock();
 
 	numqueues = READ_ONCE(tun->numqueues);
@@ -1329,6 +1324,16 @@ static int tun_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
 	return ret;
 }
 
+static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp)
+{
+	struct xdp_frame *frame = convert_to_xdp_frame(xdp);
+
+	if (unlikely(!frame))
+		return -EOVERFLOW;
+
+	return tun_xdp_xmit(dev, frame);
+}
+
 static void tun_xdp_flush(struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
@@ -1676,7 +1681,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
 		case XDP_TX:
 			get_page(alloc_frag->page);
 			alloc_frag->offset += buflen;
-			if (tun_xdp_xmit(tun->dev, &xdp))
+			if (tun_xdp_tx(tun->dev, &xdp))
 				goto err_redirect;
 			tun_xdp_flush(tun->dev);
 			rcu_read_unlock();
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index e29529880b77..d134c3041d19 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -416,10 +416,10 @@ static void virtnet_xdp_flush(struct net_device *dev)
 }
 
 static bool __virtnet_xdp_xmit(struct virtnet_info *vi,
-			       struct xdp_buff *xdp)
+			       struct xdp_frame *xdpf)
 {
 	struct virtio_net_hdr_mrg_rxbuf *hdr;
-	struct xdp_frame *xdpf, *xdpf_sent;
+	struct xdp_frame *xdpf_sent;
 	struct send_queue *sq;
 	unsigned int len;
 	unsigned int qp;
@@ -432,10 +432,6 @@ static bool __virtnet_xdp_xmit(struct virtnet_info *vi,
 	while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
 		xdp_return_frame(xdpf_sent);
 
-	xdpf = convert_to_xdp_frame(xdp);
-	if (unlikely(!xdpf))
-		return -EOVERFLOW;
-
 	/* virtqueue want to use data area in-front of packet */
 	if (unlikely(xdpf->metasize > 0))
 		return -EOPNOTSUPP;
@@ -460,7 +456,7 @@ static bool __virtnet_xdp_xmit(struct virtnet_info *vi,
 	return true;
 }
 
-static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
+static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 	struct receive_queue *rq = vi->rq;
@@ -474,7 +470,7 @@ static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
 	if (!xdp_prog)
 		return -ENXIO;
 
-	sent = __virtnet_xdp_xmit(vi, xdp);
+	sent = __virtnet_xdp_xmit(vi, xdpf);
 	if (!sent)
 		return -ENOSPC;
 	return 0;
@@ -575,6 +571,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
 	xdp_prog = rcu_dereference(rq->xdp_prog);
 	if (xdp_prog) {
 		struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
+		struct xdp_frame *xdpf;
 		struct xdp_buff xdp;
 		void *orig_data;
 		u32 act;
@@ -617,7 +614,10 @@ static struct sk_buff *receive_small(struct net_device *dev,
 			delta = orig_data - xdp.data;
 			break;
 		case XDP_TX:
-			sent = __virtnet_xdp_xmit(vi, &xdp);
+			xdpf = convert_to_xdp_frame(&xdp);
+			if (unlikely(!xdpf))
+				goto err_xdp;
+			sent = __virtnet_xdp_xmit(vi, xdpf);
 			if (unlikely(!sent)) {
 				trace_xdp_exception(vi->dev, xdp_prog, act);
 				goto err_xdp;
@@ -709,6 +709,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
 	rcu_read_lock();
 	xdp_prog = rcu_dereference(rq->xdp_prog);
 	if (xdp_prog) {
+		struct xdp_frame *xdpf;
 		struct page *xdp_page;
 		struct xdp_buff xdp;
 		void *data;
@@ -773,7 +774,10 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
 			}
 			break;
 		case XDP_TX:
-			sent = __virtnet_xdp_xmit(vi, &xdp);
+			xdpf = convert_to_xdp_frame(&xdp);
+			if (unlikely(!xdpf))
+				goto err_xdp;
+			sent = __virtnet_xdp_xmit(vi, xdpf);
 			if (unlikely(!sent)) {
 				trace_xdp_exception(vi->dev, xdp_prog, act);
 				if (unlikely(xdp_page != page))
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2a2d9cf50aa2..84a572858a08 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1164,7 +1164,7 @@ struct dev_ifalias {
  *	This function is used to set or query state related to XDP on the
  *	netdevice and manage BPF offload. See definition of
  *	enum bpf_netdev_command for details.
- * int (*ndo_xdp_xmit)(struct net_device *dev, struct xdp_buff *xdp);
+ * int (*ndo_xdp_xmit)(struct net_device *dev, struct xdp_frame *xdp);
  *	This function is used to submit a XDP packet for transmit on a
  *	netdevice.
  * void (*ndo_xdp_flush)(struct net_device *dev);
@@ -1355,7 +1355,7 @@ struct net_device_ops {
 	int			(*ndo_bpf)(struct net_device *dev,
 					   struct netdev_bpf *bpf);
 	int			(*ndo_xdp_xmit)(struct net_device *dev,
-						struct xdp_buff *xdp);
+						struct xdp_frame *xdp);
 	void			(*ndo_xdp_flush)(struct net_device *dev);
 };
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 00c711c5f1a2..2f5e185cc82b 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2748,13 +2748,18 @@ static int __bpf_tx_xdp(struct net_device *dev,
 			struct xdp_buff *xdp,
 			u32 index)
 {
+	struct xdp_frame *xdpf;
 	int err;
 
 	if (!dev->netdev_ops->ndo_xdp_xmit) {
 		return -EOPNOTSUPP;
 	}
 
-	err = dev->netdev_ops->ndo_xdp_xmit(dev, xdp);
+	xdpf = convert_to_xdp_frame(xdp);
+	if (unlikely(!xdpf))
+		return -EOVERFLOW;
+
+	err = dev->netdev_ops->ndo_xdp_xmit(dev, xdpf);
 	if (err)
 		return err;
 	dev->netdev_ops->ndo_xdp_flush(dev);
@@ -2770,11 +2775,19 @@ static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
 
 	if (map->map_type == BPF_MAP_TYPE_DEVMAP) {
 		struct net_device *dev = fwd;
+		struct xdp_frame *xdpf;
 
 		if (!dev->netdev_ops->ndo_xdp_xmit)
 			return -EOPNOTSUPP;
 
-		err = dev->netdev_ops->ndo_xdp_xmit(dev, xdp);
+		xdpf = convert_to_xdp_frame(xdp);
+		if (unlikely(!xdpf))
+			return -EOVERFLOW;
+
+		/* TODO: move to inside map code instead, for bulk support
+		 * err = dev_map_enqueue(dev, xdp);
+		 */
+		err = dev->netdev_ops->ndo_xdp_xmit(dev, xdpf);
 		if (err)
 			return err;
 		__dev_map_insert_ctx(map, index);

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox