* [PATCH net] bnxt_en: Fix "uninitialized variable" bug in TPA code path.
From: Michael Chan @ 2017-01-18 3:07 UTC (permalink / raw)
To: davem; +Cc: netdev, andrew.gospodarek
In the TPA GRO code path, initialize the tcp_opt_len variable to 0 so
that it will be correct for packets without TCP timestamps. The bug
caused the SKB fields to be incorrectly set up for packets without
TCP timestamps, leading to these packets being rejected by the stack.
Reported-by: Andy Gospodarek <andrew.gospodarek@broadocm.com>
Acked-by: Andy Gospodarek <andrew.gospodarek@broadocm.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 9608cb4..53e686f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1099,7 +1099,7 @@ static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info,
{
#ifdef CONFIG_INET
struct tcphdr *th;
- int len, nw_off, tcp_opt_len;
+ int len, nw_off, tcp_opt_len = 0;
if (tcp_ts)
tcp_opt_len = 12;
--
1.8.3.1
^ permalink raw reply related
* RE: [PATCH] net: fec: Fixed panic problem with non-tso
From: Ashizuka, Yuusuke @ 2017-01-18 3:20 UTC (permalink / raw)
To: David Miller; +Cc: fugang.duan@nxp.com, netdev@vger.kernel.org
In-Reply-To: <20170117.154512.612465430064515761.davem@davemloft.net>
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Wednesday, January 18, 2017 5:45 AM
> To: Ashizuka, Yuusuke/芦塚 雄介
> Cc: fugang.duan@nxp.com; netdev@vger.kernel.org
> Subject: Re: [PATCH] net: fec: Fixed panic problem with non-tso
>
> From: Yuusuke Ashiduka <ashiduka@jp.fujitsu.com>
> Date: Tue, 17 Jan 2017 16:48:20 +0900
>
> > If highmem and 2GB or more of memory are valid, "this_frag-> page.p"
> > indicates the highmem area, so the result of page_address() is NULL
> > and panic occurs.
> >
> > This commit fixes this by using the skb_frag_dma_map() helper, which
> > takes care of mapping the skb fragment properly. Additionally, the
> > type of mapping is now tracked, so it can be unmapped using
> > dma_unmap_page or dma_unmap_single when appropriate.
>
> This patch submission is lacking a proper signoff.
Thank you for pointing out my mistake.
I will submit the patch again.
^ permalink raw reply
* RE: [PATCH] net: fec: Fixed panic problem with non-tso
From: Ashizuka, Yuusuke @ 2017-01-18 3:12 UTC (permalink / raw)
To: Andy Duan; +Cc: netdev@vger.kernel.org
In-Reply-To: <AM4PR0401MB2260E5BE096D7B86EDF4F04FFF7C0@AM4PR0401MB2260.eurprd04.prod.outlook.com>
> -----Original Message-----
> From: Andy Duan [mailto:fugang.duan@nxp.com]
> Sent: Tuesday, January 17, 2017 8:02 PM
> To: Ashizuka, Yuusuke/芦塚 雄介
> Cc: netdev@vger.kernel.org
> Subject: RE: [PATCH] net: fec: Fixed panic problem with non-tso
>
> From: Yuusuke Ashiduka <ashiduka@jp.fujitsu.com> Sent: Tuesday, January
> 17, 2017 3:48 PM
> >To: Andy Duan <fugang.duan@nxp.com>
> >Cc: netdev@vger.kernel.org; Yuusuke Ashiduka <ashiduka@jp.fujitsu.com>
> >Subject: [PATCH] net: fec: Fixed panic problem with non-tso
> >
> >If highmem and 2GB or more of memory are valid, "this_frag-> page.p"
> >indicates the highmem area, so the result of page_address() is NULL and
> >panic occurs.
> >
> >This commit fixes this by using the skb_frag_dma_map() helper, which
> >takes care of mapping the skb fragment properly. Additionally, the type
> >of mapping is now tracked, so it can be unmapped using dma_unmap_page
> >or dma_unmap_single when appropriate.
> >---
> > drivers/net/ethernet/freescale/fec.h | 1 +
> > drivers/net/ethernet/freescale/fec_main.c | 48
> >+++++++++++++++++++++++--------
> > 2 files changed, 37 insertions(+), 12 deletions(-)
> >
> The patch itself seems fine.
> The driver doesn't support skb from highmem, if to support highmem, it should
> add frag_skb (highmem) support for tso and non-tso.
> In driver net/core/tso.c, it also add highmem support, right ?
indeed.
In the case of TSO with i.MX6 system (highmem enabled) with 2GB memory,
"this_frag->page.p" did not become highmem area.
(We confirmed by transferring about 100MB of files)
However, in the case of non-tso on an i.MX6 system with 2GB of memory,
"this_frag->page.p" may become a highmem area.
(Occurred with approximately 2MB of file transfer)
For non-tso only, I do not know the reason why "this_frag-> page.p"
in this driver shows highmem area.
Thanks.
>
> Thanks.
>
> >diff --git a/drivers/net/ethernet/freescale/fec.h
> >b/drivers/net/ethernet/freescale/fec.h
> >index 5ea740b4cf14..5b187e8aacf0 100644
> >--- a/drivers/net/ethernet/freescale/fec.h
> >+++ b/drivers/net/ethernet/freescale/fec.h
> >@@ -463,6 +463,7 @@ struct bufdesc_prop { struct fec_enet_priv_tx_q {
> > struct bufdesc_prop bd;
> > unsigned char *tx_bounce[TX_RING_SIZE];
> >+ int tx_page_mapping[TX_RING_SIZE];
> > struct sk_buff *tx_skbuff[TX_RING_SIZE];
> >
> > unsigned short tx_stop_threshold;
> >diff --git a/drivers/net/ethernet/freescale/fec_main.c
> >b/drivers/net/ethernet/freescale/fec_main.c
> >index 38160c2bebcb..b1562107e337 100644
> >--- a/drivers/net/ethernet/freescale/fec_main.c
> >+++ b/drivers/net/ethernet/freescale/fec_main.c
> >@@ -60,6 +60,7 @@
> > #include <linux/if_vlan.h>
> > #include <linux/pinctrl/consumer.h>
> > #include <linux/prefetch.h>
> >+#include <linux/highmem.h>
> > #include <soc/imx/cpuidle.h>
> >
> > #include <asm/cacheflush.h>
> >@@ -377,20 +378,28 @@ fec_enet_txq_submit_frag_skb(struct
> >fec_enet_priv_tx_q *txq,
> > ebdp->cbd_esc = cpu_to_fec32(estatus);
> > }
> >
> >- bufaddr = page_address(this_frag->page.p) + this_frag-
> >>page_offset;
> >-
> > index = fec_enet_get_bd_index(bdp, &txq->bd);
> >- if (((unsigned long) bufaddr) & fep->tx_align ||
> >+ txq->tx_page_mapping[index] = 0;
> >+ if (this_frag->page_offset & fep->tx_align ||
> > fep->quirks & FEC_QUIRK_SWAP_FRAME) {
> >+ bufaddr = kmap_atomic(this_frag->page.p) +
> >+
> this_frag->page_offset;
> > memcpy(txq->tx_bounce[index], bufaddr,
> frag_len);
> >+ kunmap_atomic(bufaddr);
> > bufaddr = txq->tx_bounce[index];
> >
> > if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
> > swap_buffer(bufaddr, frag_len);
> >+ addr = dma_map_single(&fep->pdev->dev,
> >+ bufaddr,
> >+ frag_len,
> >+ DMA_TO_DEVICE);
> >+ } else {
> >+ txq->tx_page_mapping[index] = 1;
> >+ addr = skb_frag_dma_map(&fep->pdev->dev,
> >this_frag, 0,
> >+ frag_len,
> DMA_TO_DEVICE);
> > }
> >
> >- addr = dma_map_single(&fep->pdev->dev, bufaddr,
> frag_len,
> >- DMA_TO_DEVICE);
> > if (dma_mapping_error(&fep->pdev->dev, addr)) {
> > if (net_ratelimit())
> > netdev_err(ndev, "Tx DMA memory map
> failed\n"); @@ -411,8 +420,16
> >@@ fec_enet_txq_submit_frag_skb(struct
> >fec_enet_priv_tx_q *txq,
> > bdp = txq->bd.cur;
> > for (i = 0; i < frag; i++) {
> > bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
> >- dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp-
> >>cbd_bufaddr),
> >- fec16_to_cpu(bdp->cbd_datlen),
> >DMA_TO_DEVICE);
> >+ if (txq->tx_page_mapping[index])
> >+ dma_unmap_page(&fep->pdev->dev,
> >+ fec32_to_cpu(bdp->cbd_bufaddr),
> >+ fec16_to_cpu(bdp->cbd_datlen),
> >+ DMA_TO_DEVICE);
> >+ else
> >+ dma_unmap_single(&fep->pdev->dev,
> >+
> fec32_to_cpu(bdp->cbd_bufaddr),
> >+
> fec16_to_cpu(bdp->cbd_datlen),
> >+ DMA_TO_DEVICE);
> > }
> > return ERR_PTR(-ENOMEM);
> > }
> >@@ -1201,11 +1218,18 @@ fec_enet_tx_queue(struct net_device *ndev, u16
> >queue_id)
> >
> > skb = txq->tx_skbuff[index];
> > txq->tx_skbuff[index] = NULL;
> >- if (!IS_TSO_HEADER(txq,
> fec32_to_cpu(bdp->cbd_bufaddr)))
> >- dma_unmap_single(&fep->pdev->dev,
> >-
> fec32_to_cpu(bdp->cbd_bufaddr),
> >-
> fec16_to_cpu(bdp->cbd_datlen),
> >- DMA_TO_DEVICE);
> >+ if (!IS_TSO_HEADER(txq,
> fec32_to_cpu(bdp->cbd_bufaddr)))
> >{
> >+ if (txq->tx_page_mapping[index])
> >+ dma_unmap_page(&fep->pdev->dev,
> >+
> fec32_to_cpu(bdp->cbd_bufaddr),
> >+
> fec16_to_cpu(bdp->cbd_datlen),
> >+ DMA_TO_DEVICE);
> >+ else
> >+ dma_unmap_single(&fep->pdev->dev,
> >+ fec32_to_cpu(bdp-
> >>cbd_bufaddr),
> >+ fec16_to_cpu(bdp-
> >>cbd_datlen),
> >+ DMA_TO_DEVICE);
> >+ }
> > bdp->cbd_bufaddr = cpu_to_fec32(0);
> > if (!skb)
> > goto skb_done;
> >--
> >2.11.0
^ permalink raw reply
* Re: [net PATCH v5 6/6] virtio_net: XDP support for adjust_head
From: Jason Wang @ 2017-01-18 3:35 UTC (permalink / raw)
To: John Fastabend, mst; +Cc: john.r.fastabend, netdev, alexei.starovoitov, daniel
In-Reply-To: <20170117222259.20280.24625.stgit@john-Precision-Tower-5810>
On 2017年01月18日 06:22, John Fastabend wrote:
>
> +static int virtnet_reset(struct virtnet_info *vi)
> +{
> + struct virtio_device *dev = vi->vdev;
> + int ret;
> +
> + virtio_config_disable(dev);
> + dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
> + virtnet_freeze_down(dev);
> + _remove_vq_common(vi);
> +
> + dev->config->reset(dev);
> + virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> +
> + ret = virtio_finalize_features(dev);
> + if (ret)
> + goto err;
> +
> + ret = virtnet_restore_up(dev);
> + if (ret)
> + goto err;
> + ret = _virtnet_set_queues(vi, vi->curr_queue_pairs);
> + if (ret)
> + goto err;
> +
> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> + virtio_config_enable(dev);
> + return 0;
> +err:
> + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
> + return ret;
> +}
> +
Hi John:
I still prefer not open code (part of) virtio_device_freeze() and
virtio_device_restore() here. How about:
1) introduce __virtio_device_freeze/__virtio_device_restore which
accepts a function pointer of free/restore
2) for virtio_device_freeze/virtio_device_restore just pass
drv->freeze/drv->restore (locked version)
3) for virtnet_reset(), we can pass unlocked version of freeze and restore
Just my preference, if both Michael and you stick to this, I'm also fine.
Thanks
^ permalink raw reply
* Re: [PATCH] virtio: don't set VIRTIO_NET_HDR_F_DATA_VALID on xmit
From: Jason Wang @ 2017-01-18 3:54 UTC (permalink / raw)
To: Michael S. Tsirkin, Rolf Neugebauer; +Cc: netdev, davem, rppt
In-Reply-To: <20170117202515-mutt-send-email-mst@kernel.org>
On 2017年01月18日 02:27, Michael S. Tsirkin wrote:
> On Tue, Jan 17, 2017 at 06:13:51PM +0000, Rolf Neugebauer wrote:
>> This patch part reverts fd2a0437dc33 and e858fae2b0b8 which introduced a
>> subtle change in how the virtio_net flags are derived from the SKBs
>> ip_summed field.
>>
>> With the above commits, the flags are set to VIRTIO_NET_HDR_F_DATA_VALID
>> when ip_summed == CHECKSUM_UNNECESSARY, thus treating it differently to
>> ip_summed == CHECKSUM_NONE, which should be the same.
>>
>> Further, the virtio spec 1.0 / CS04 explicitly says that
>> VIRTIO_NET_HDR_F_DATA_VALID must not be set by the driver.
>>
>> Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
> Fixes: fd2a0437dc33 ("virtio_net: introduce virtio_net_hdr_{from,to}_skb")
> Fixes: e858fae2b0b8 (" virtio_net: use common code for virtio_net_hdr and skb GSO conversion")
> Acked-by: Michael S. Tsirkin <mst@redhat.com>
>
> Should be backported into stable as well.
Looks like a side effect is that we will never see this on receive path?
We probably need a hint for virtio_net_hdr_from_skb().
Thanks
>
>
>> ---
>> include/linux/virtio_net.h | 2 --
>> 1 file changed, 2 deletions(-)
>>
>> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
>> index 66204007d7ac..56436472ccc7 100644
>> --- a/include/linux/virtio_net.h
>> +++ b/include/linux/virtio_net.h
>> @@ -91,8 +91,6 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
>> skb_checksum_start_offset(skb));
>> hdr->csum_offset = __cpu_to_virtio16(little_endian,
>> skb->csum_offset);
>> - } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
>> - hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
>> } /* else everything is zero */
>>
>> return 0;
>> --
>> 2.11.0
^ permalink raw reply
* [PATCH v2] net: fec: Fixed panic problem with non-tso
From: Yuusuke Ashiduka @ 2017-01-18 4:11 UTC (permalink / raw)
To: fugang.duan; +Cc: netdev, Yuusuke Ashiduka
In-Reply-To: <20170117.154512.612465430064515761.davem@davemloft.net>
If highmem and 2GB or more of memory are valid,
"this_frag-> page.p" indicates the highmem area,
so the result of page_address() is NULL and panic occurs.
This commit fixes this by using the skb_frag_dma_map() helper,
which takes care of mapping the skb fragment properly. Additionally,
the type of mapping is now tracked, so it can be unmapped using
dma_unmap_page or dma_unmap_single when appropriate.
Signed-off-by: Yuusuke Ashiduka <ashiduka@jp.fujitsu.com>
---
Changes for v2:
- Added signed-off
---
drivers/net/ethernet/freescale/fec.h | 1 +
drivers/net/ethernet/freescale/fec_main.c | 48 +++++++++++++++++++++++--------
2 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5ea740b4cf14..5b187e8aacf0 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -463,6 +463,7 @@ struct bufdesc_prop {
struct fec_enet_priv_tx_q {
struct bufdesc_prop bd;
unsigned char *tx_bounce[TX_RING_SIZE];
+ int tx_page_mapping[TX_RING_SIZE];
struct sk_buff *tx_skbuff[TX_RING_SIZE];
unsigned short tx_stop_threshold;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 38160c2bebcb..b1562107e337 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -60,6 +60,7 @@
#include <linux/if_vlan.h>
#include <linux/pinctrl/consumer.h>
#include <linux/prefetch.h>
+#include <linux/highmem.h>
#include <soc/imx/cpuidle.h>
#include <asm/cacheflush.h>
@@ -377,20 +378,28 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
ebdp->cbd_esc = cpu_to_fec32(estatus);
}
- bufaddr = page_address(this_frag->page.p) + this_frag->page_offset;
-
index = fec_enet_get_bd_index(bdp, &txq->bd);
- if (((unsigned long) bufaddr) & fep->tx_align ||
+ txq->tx_page_mapping[index] = 0;
+ if (this_frag->page_offset & fep->tx_align ||
fep->quirks & FEC_QUIRK_SWAP_FRAME) {
+ bufaddr = kmap_atomic(this_frag->page.p) +
+ this_frag->page_offset;
memcpy(txq->tx_bounce[index], bufaddr, frag_len);
+ kunmap_atomic(bufaddr);
bufaddr = txq->tx_bounce[index];
if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
swap_buffer(bufaddr, frag_len);
+ addr = dma_map_single(&fep->pdev->dev,
+ bufaddr,
+ frag_len,
+ DMA_TO_DEVICE);
+ } else {
+ txq->tx_page_mapping[index] = 1;
+ addr = skb_frag_dma_map(&fep->pdev->dev, this_frag, 0,
+ frag_len, DMA_TO_DEVICE);
}
- addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
- DMA_TO_DEVICE);
if (dma_mapping_error(&fep->pdev->dev, addr)) {
if (net_ratelimit())
netdev_err(ndev, "Tx DMA memory map failed\n");
@@ -411,8 +420,16 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
bdp = txq->bd.cur;
for (i = 0; i < frag; i++) {
bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
- dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr),
- fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE);
+ if (txq->tx_page_mapping[index])
+ dma_unmap_page(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
}
return ERR_PTR(-ENOMEM);
}
@@ -1201,11 +1218,18 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
skb = txq->tx_skbuff[index];
txq->tx_skbuff[index] = NULL;
- if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
- dma_unmap_single(&fep->pdev->dev,
- fec32_to_cpu(bdp->cbd_bufaddr),
- fec16_to_cpu(bdp->cbd_datlen),
- DMA_TO_DEVICE);
+ if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) {
+ if (txq->tx_page_mapping[index])
+ dma_unmap_page(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ }
bdp->cbd_bufaddr = cpu_to_fec32(0);
if (!skb)
goto skb_done;
--
2.11.0
^ permalink raw reply related
* Re: [PATCH] net: fec: Fixed panic problem with non-tso
From: Eric Dumazet @ 2017-01-18 4:21 UTC (permalink / raw)
To: Ashizuka, Yuusuke; +Cc: Andy Duan, netdev@vger.kernel.org
In-Reply-To: <337A096076BEF646A1F21E1AD855580E3AC8F71A@g01jpexmbkw23>
On Wed, 2017-01-18 at 03:12 +0000, Ashizuka, Yuusuke wrote:
> indeed.
>
> In the case of TSO with i.MX6 system (highmem enabled) with 2GB memory,
> "this_frag->page.p" did not become highmem area.
> (We confirmed by transferring about 100MB of files)
>
> However, in the case of non-tso on an i.MX6 system with 2GB of memory,
> "this_frag->page.p" may become a highmem area.
> (Occurred with approximately 2MB of file transfer)
>
> For non-tso only, I do not know the reason why "this_frag-> page.p"
> in this driver shows highmem area.
This worries me, since this driver does not set NETIF_F_HIGHDMA in its
features.
No packet should be given to this driver with a highmem fragment
Check is done in illegal_highdma() in net/core/dev.c
^ permalink raw reply
* Re: [PATCH] net: fec: Fixed panic problem with non-tso
From: Eric Dumazet @ 2017-01-18 4:35 UTC (permalink / raw)
To: Ashizuka, Yuusuke; +Cc: Andy Duan, netdev@vger.kernel.org, Pravin B Shelar
In-Reply-To: <1484713283.13165.89.camel@edumazet-glaptop3.roam.corp.google.com>
On Tue, 2017-01-17 at 20:21 -0800, Eric Dumazet wrote:
> On Wed, 2017-01-18 at 03:12 +0000, Ashizuka, Yuusuke wrote:
>
> > indeed.
> >
> > In the case of TSO with i.MX6 system (highmem enabled) with 2GB memory,
> > "this_frag->page.p" did not become highmem area.
> > (We confirmed by transferring about 100MB of files)
> >
> > However, in the case of non-tso on an i.MX6 system with 2GB of memory,
> > "this_frag->page.p" may become a highmem area.
> > (Occurred with approximately 2MB of file transfer)
> >
> > For non-tso only, I do not know the reason why "this_frag-> page.p"
> > in this driver shows highmem area.
>
> This worries me, since this driver does not set NETIF_F_HIGHDMA in its
> features.
>
> No packet should be given to this driver with a highmem fragment
>
> Check is done in illegal_highdma() in net/core/dev.c
This used to work.
I suspect commit ec5f061564238892005257c83565a0b58ec79295
("net: Kill link between CSUM and SG features.")
added this bug.
Can you try this hot fix :
diff --git a/net/core/dev.c b/net/core/dev.c
index ad5959e561166f445bdd9d7260652a338f74cfea..073b832b945257dba9ed47f4bf875605225effc9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2773,9 +2773,9 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
if (skb->ip_summed != CHECKSUM_NONE &&
!can_checksum_protocol(features, type)) {
features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
- } else if (illegal_highdma(skb->dev, skb)) {
- features &= ~NETIF_F_SG;
}
+ if (illegal_highdma(skb->dev, skb))
+ features &= ~NETIF_F_SG;
return features;
}
^ permalink raw reply related
* [PATCH net-next] mlx4: support __GFP_MEMALLOC for rx
From: Eric Dumazet @ 2017-01-18 4:14 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Konstantin Khlebnikov, Tariq Toukan
From: Eric Dumazet <edumazet@google.com>
Commit 04aeb56a1732 ("net/mlx4_en: allocate non 0-order pages for RX
ring with __GFP_NOMEMALLOC") added code that appears to be not needed at
that time, since mlx4 never used __GFP_MEMALLOC allocations anyway.
As using memory reserves is a must in some situations (swap over NFS or
iSCSI), this patch adds this flag.
Note that this driver does not reuse pages (yet) so we do not have to
add anything else.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Cc: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index eac527e25ec902c2a586e9952272b9e8e599e2c8..e362f99334d03c0df4d88320977670015870dd9c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -706,7 +706,8 @@ static bool mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
do {
if (mlx4_en_prepare_rx_desc(priv, ring,
ring->prod & ring->size_mask,
- GFP_ATOMIC | __GFP_COLD))
+ GFP_ATOMIC | __GFP_COLD |
+ __GFP_MEMALLOC))
break;
ring->prod++;
} while (--missing);
^ permalink raw reply related
* Re: [PATCH v2] net: fec: Fixed panic problem with non-tso
From: Eric Dumazet @ 2017-01-18 5:02 UTC (permalink / raw)
To: Yuusuke Ashiduka; +Cc: fugang.duan, netdev
In-Reply-To: <20170118041140.15371-1-ashiduka@jp.fujitsu.com>
On Wed, 2017-01-18 at 13:11 +0900, Yuusuke Ashiduka wrote:
> If highmem and 2GB or more of memory are valid,
> "this_frag-> page.p" indicates the highmem area,
> so the result of page_address() is NULL and panic occurs.
>
> This commit fixes this by using the skb_frag_dma_map() helper,
> which takes care of mapping the skb fragment properly. Additionally,
> the type of mapping is now tracked, so it can be unmapped using
> dma_unmap_page or dma_unmap_single when appropriate.
I would prefer we fix the root cause, instead of tweaking all legacy
drivers out there :/
^ permalink raw reply
* RE: [PATCH v2] net: fec: Fixed panic problem with non-tso
From: Andy Duan @ 2017-01-18 5:38 UTC (permalink / raw)
To: Eric Dumazet, Yuusuke Ashiduka; +Cc: netdev@vger.kernel.org
In-Reply-To: <1484715738.13165.95.camel@edumazet-glaptop3.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com> Sent: Wednesday, January 18, 2017 1:02 PM
>To: Yuusuke Ashiduka <ashiduka@jp.fujitsu.com>
>Cc: Andy Duan <fugang.duan@nxp.com>; netdev@vger.kernel.org
>Subject: Re: [PATCH v2] net: fec: Fixed panic problem with non-tso
>
>On Wed, 2017-01-18 at 13:11 +0900, Yuusuke Ashiduka wrote:
>> If highmem and 2GB or more of memory are valid, "this_frag-> page.p"
>> indicates the highmem area, so the result of page_address() is NULL
>> and panic occurs.
>>
>> This commit fixes this by using the skb_frag_dma_map() helper, which
>> takes care of mapping the skb fragment properly. Additionally, the
>> type of mapping is now tracked, so it can be unmapped using
>> dma_unmap_page or dma_unmap_single when appropriate.
>
>
>I would prefer we fix the root cause, instead of tweaking all legacy drivers out
>there :/
>
>
I agree with you.
The driver always doesn't support highmem. The fragment shouldn't allocate from highmem except the common code bug.
If request the driver to support NETIF_F_HIGHDMA feature, we also add highmem support for tso driver.
Andy
^ permalink raw reply
* Re: [RFC v2 00/10] HFI Virtual Network Interface Controller (VNIC)
From: Leon Romanovsky @ 2017-01-18 5:43 UTC (permalink / raw)
To: Vishwanathapura, Niranjana
Cc: Jason Gunthorpe, ira.weiny, Doug Ledford, Jeff Kirsher,
David S. Miller, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
dennis.dalessandro-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <20170117192720.GA2833-wPcXA7LoDC+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 2604 bytes --]
On Tue, Jan 17, 2017 at 11:27:20AM -0800, Vishwanathapura, Niranjana wrote:
> Thanks Jason for the valuable inputs.
>
> Here is the new generic interface.
>
> Overview:
> Bottom driver defines net_device_ops. The upper driver can override it.
> For example, upper driver can implement ndo_open() which calls bottom
> driver's ndo_open() and also do some book keeping.
>
>
> include/rdma/ib_verbs.h:
>
> /* rdma netdev type - specifies protocol type */
> enum rdma_netdev_t {
> RDMA_NETDEV_HFI_VNIC,
> };
>
> /* rdma netdev
> * For usecases where netstack interfacing is required.
> */
> struct rdma_netdev {
> struct net_device *netdev;
> u8 port_num;
>
> /* client private data structure */
> void *clnt_priv;
>
> /* control functions */
> void (*set_id)(struct rdma_netdev *rn, int id);
> void (*set_state)(struct rdma_netdev *rn, int state);
> };
>
> struct ib_device {
> ...
> ...
> /* rdma netdev operations */
> struct net_device *(*alloc_rdma_netdev)(struct ib_device *device,
> u8 port_num,
> enum rdma_netdev_t type,
> const char *name,
> unsigned char name_assign_type,
> void (*setup)(struct net_device *));
> void (*free_rdma_netdev)(struct net_device *netdev);
> };
>
>
> hfi1 driver:
>
> /* rdma netdev's private data structure */
> struct hfi1_rdma_netdev {
> struct rdma_netdev rn; /* keep this first */
> /* hfi1's vnic private data follows */
> };
>
>
> include/rdma/opa_hfi.h:
>
> /* Client's ndo operations use below function instead of netdev_priv() */
> static inline void *hfi_vnic_priv(const struct net_device *dev)
> {
> struct rdma_netdev *rn = netdev_priv(dev);
>
> return rn->clnt_priv;
> }
>
> /* Overrides rtnl_link_stats64 to include hfi_vnic stats.
> * ndo_get_stats64() can be used to get the stats
> */
> struct hfi_vnic_stats {
> /* standard netdev statistics */
> struct rtnl_link_stats64 netstat;
>
> /* HFI VNIC statistics */
> u64 tx_mcastbcast;
> u64 tx_untagged;
> u64 tx_vlan;
> u64 tx_64_size;
> u64 tx_65_127;
> u64 tx_128_255;
> u64 tx_256_511;
> u64 tx_512_1023;
> u64 tx_1024_1518;
> u64 tx_1519_max;
>
> u64 rx_untagged;
> u64 rx_vlan;
> u64 rx_64_size;
> u64 rx_65_127;
> u64 rx_128_255;
> u64 rx_256_511;
> u64 rx_512_1023;
> u64 rx_1024_1518;
> u64 rx_1519_max;
>
> u64 rx_runt;
> u64 rx_oversize;
> };
>
> I have started working on porting hfi_vnic as per this new interface.
> I will post RFC v3 later.
> Posting the interface definition early for comments.
I wonder how many people will comment it without seeing usage example.
>
> Thanks,
> Niranjana
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v2] bridge: multicast to unicast
From: kbuild test robot @ 2017-01-18 5:59 UTC (permalink / raw)
To: Linus Lüssing
Cc: kbuild-all, netdev, David S . Miller, Stephen Hemminger,
Felix Fietkau, Nikolay Aleksandrov, bridge, linux-kernel,
linux-wireless, Linus Lüssing
In-Reply-To: <20170117195917.16209-1-linus.luessing@c0d3.blue>
[-- Attachment #1: Type: text/plain, Size: 3250 bytes --]
Hi Felix,
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Linus-L-ssing/bridge-multicast-to-unicast/20170118-120345
config: x86_64-rhel-7.2 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings
All warnings (new ones prefixed by >>):
net/bridge/br_forward.c: In function 'br_multicast_flood':
>> net/bridge/br_forward.c:261:27: warning: 'port' may be used uninitialized in this function [-Wmaybe-uninitialized]
struct net_bridge_port *port, *lport, *rport;
^~~~
vim +/port +261 net/bridge/br_forward.c
5cb5e947 Herbert Xu 2010-02-27 245 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
5cb5e947 Herbert Xu 2010-02-27 246 /* called with rcu_read_lock */
37b090e6 Nikolay Aleksandrov 2016-07-14 247 void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
b35c5f63 Nikolay Aleksandrov 2016-07-14 248 struct sk_buff *skb,
37b090e6 Nikolay Aleksandrov 2016-07-14 249 bool local_rcv, bool local_orig)
5cb5e947 Herbert Xu 2010-02-27 250 {
5cb5e947 Herbert Xu 2010-02-27 251 struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
1080ab95 Nikolay Aleksandrov 2016-06-28 252 u8 igmp_type = br_multicast_igmp_type(skb);
5cb5e947 Herbert Xu 2010-02-27 253 struct net_bridge *br = netdev_priv(dev);
afe0159d stephen hemminger 2010-04-27 254 struct net_bridge_port *prev = NULL;
5cb5e947 Herbert Xu 2010-02-27 255 struct net_bridge_port_group *p;
5cb5e947 Herbert Xu 2010-02-27 256 struct hlist_node *rp;
5cb5e947 Herbert Xu 2010-02-27 257
e8051688 Eric Dumazet 2010-11-15 258 rp = rcu_dereference(hlist_first_rcu(&br->router_list));
83f6a740 stephen hemminger 2010-04-27 259 p = mdst ? rcu_dereference(mdst->ports) : NULL;
5cb5e947 Herbert Xu 2010-02-27 260 while (p || rp) {
afe0159d stephen hemminger 2010-04-27 @261 struct net_bridge_port *port, *lport, *rport;
afe0159d stephen hemminger 2010-04-27 262
5cb5e947 Herbert Xu 2010-02-27 263 lport = p ? p->port : NULL;
5cb5e947 Herbert Xu 2010-02-27 264 rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
5cb5e947 Herbert Xu 2010-02-27 265 NULL;
5cb5e947 Herbert Xu 2010-02-27 266
507962cd Felix Fietkau 2017-01-17 267 if ((unsigned long)lport > (unsigned long)rport) {
507962cd Felix Fietkau 2017-01-17 268 if (p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) {
507962cd Felix Fietkau 2017-01-17 269 maybe_deliver_addr(lport, skb, p->eth_addr,
:::::: The code at line 261 was first introduced by commit
:::::: afe0159d935ab731c682e811356914bb2be9470c bridge: multicast_flood cleanup
:::::: TO: stephen hemminger <shemminger@vyatta.com>
:::::: CC: David S. Miller <davem@davemloft.net>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 38262 bytes --]
^ permalink raw reply
* [PATCH net-next v2] net/mlx5e: Support bpf_xdp_adjust_head()
From: Martin KaFai Lau @ 2017-01-18 6:06 UTC (permalink / raw)
To: netdev; +Cc: Saeed Mahameed, Tariq Toukan, Kernel Team
This patch adds bpf_xdp_adjust_head() support to mlx5e.
1. rx_headroom is added to struct mlx5e_rq. It uses
an existing 4 byte hole in the struct.
2. The adjusted data length is checked against
MLX5E_XDP_MIN_INLINE and MLX5E_SW2HW_MTU(rq->netdev->mtu).
3. The macro MLX5E_SW2HW_MTU is moved from en_main.c to en.h.
MLX5E_HW2SW_MTU is also moved to en.h for symmetric reason
but it is not a must.
v2:
- Keep the xdp specific logic in mlx5e_xdp_handle()
- Update dma_len after the sanity checks in mlx5e_xmit_xdp_frame()
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 4 ++
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 18 ++++-----
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 47 ++++++++++++++---------
3 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index a473cea10c16..0d9dd860a295 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -51,6 +51,9 @@
#define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v)
+#define MLX5E_HW2SW_MTU(hwmtu) ((hwmtu) - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
+#define MLX5E_SW2HW_MTU(swmtu) ((swmtu) + (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
+
#define MLX5E_MAX_NUM_TC 8
#define MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE 0x6
@@ -369,6 +372,7 @@ struct mlx5e_rq {
unsigned long state;
int ix;
+ u16 rx_headroom;
struct mlx5e_rx_am am; /* Adaptive Moderation */
struct bpf_prog *xdp_prog;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index f74ba73c55c7..aba3691e0919 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -343,9 +343,6 @@ static void mlx5e_disable_async_events(struct mlx5e_priv *priv)
synchronize_irq(mlx5_get_msix_vec(priv->mdev, MLX5_EQ_VEC_ASYNC));
}
-#define MLX5E_HW2SW_MTU(hwmtu) (hwmtu - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
-#define MLX5E_SW2HW_MTU(swmtu) (swmtu + (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
-
static inline int mlx5e_get_wqe_mtt_sz(void)
{
/* UMR copies MTTs in units of MLX5_UMR_MTT_ALIGNMENT bytes.
@@ -534,9 +531,13 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
goto err_rq_wq_destroy;
}
- rq->buff.map_dir = DMA_FROM_DEVICE;
- if (rq->xdp_prog)
+ if (rq->xdp_prog) {
rq->buff.map_dir = DMA_BIDIRECTIONAL;
+ rq->rx_headroom = XDP_PACKET_HEADROOM;
+ } else {
+ rq->buff.map_dir = DMA_FROM_DEVICE;
+ rq->rx_headroom = MLX5_RX_HEADROOM;
+ }
switch (priv->params.rq_wq_type) {
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
@@ -586,7 +587,7 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
byte_count = rq->buff.wqe_sz;
/* calc the required page order */
- frag_sz = MLX5_RX_HEADROOM +
+ frag_sz = rq->rx_headroom +
byte_count /* packet data */ +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
frag_sz = SKB_DATA_ALIGN(frag_sz);
@@ -3153,11 +3154,6 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
bool reset, was_opened;
int i;
- if (prog && prog->xdp_adjust_head) {
- netdev_err(netdev, "Does not support bpf_xdp_adjust_head()\n");
- return -EOPNOTSUPP;
- }
-
mutex_lock(&priv->state_lock);
if ((netdev->features & NETIF_F_LRO) && prog) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 0e2fb3ed1790..20f116f8c457 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -264,7 +264,7 @@ int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix)
if (unlikely(mlx5e_page_alloc_mapped(rq, di)))
return -ENOMEM;
- wqe->data.addr = cpu_to_be64(di->addr + MLX5_RX_HEADROOM);
+ wqe->data.addr = cpu_to_be64(di->addr + rq->rx_headroom);
return 0;
}
@@ -646,8 +646,7 @@ static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_sq *sq)
static inline void mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
struct mlx5e_dma_info *di,
- unsigned int data_offset,
- int len)
+ const struct xdp_buff *xdp)
{
struct mlx5e_sq *sq = &rq->channel->xdp_sq;
struct mlx5_wq_cyc *wq = &sq->wq;
@@ -659,9 +658,16 @@ static inline void mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
struct mlx5_wqe_eth_seg *eseg = &wqe->eth;
struct mlx5_wqe_data_seg *dseg;
+ ptrdiff_t data_offset = xdp->data - xdp->data_hard_start;
dma_addr_t dma_addr = di->addr + data_offset + MLX5E_XDP_MIN_INLINE;
- unsigned int dma_len = len - MLX5E_XDP_MIN_INLINE;
- void *data = page_address(di->page) + data_offset;
+ unsigned int dma_len = xdp->data_end - xdp->data;
+
+ if (unlikely(dma_len < MLX5E_XDP_MIN_INLINE ||
+ MLX5E_SW2HW_MTU(rq->netdev->mtu) < dma_len)) {
+ rq->stats.xdp_drop++;
+ mlx5e_page_release(rq, di, true);
+ return;
+ }
if (unlikely(!mlx5e_sq_has_room_for(sq, MLX5E_XDP_TX_WQEBBS))) {
if (sq->db.xdp.doorbell) {
@@ -674,13 +680,14 @@ static inline void mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
return;
}
+ dma_len -= MLX5E_XDP_MIN_INLINE;
dma_sync_single_for_device(sq->pdev, dma_addr, dma_len,
PCI_DMA_TODEVICE);
memset(wqe, 0, sizeof(*wqe));
/* copy the inline part */
- memcpy(eseg->inline_hdr_start, data, MLX5E_XDP_MIN_INLINE);
+ memcpy(eseg->inline_hdr_start, xdp->data, MLX5E_XDP_MIN_INLINE);
eseg->inline_hdr_sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE);
dseg = (struct mlx5_wqe_data_seg *)cseg + (MLX5E_XDP_TX_DS_COUNT - 1);
@@ -703,25 +710,29 @@ static inline void mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
}
/* returns true if packet was consumed by xdp */
-static inline bool mlx5e_xdp_handle(struct mlx5e_rq *rq,
- const struct bpf_prog *prog,
- struct mlx5e_dma_info *di,
- void *data, u16 len)
+static inline int mlx5e_xdp_handle(struct mlx5e_rq *rq,
+ struct mlx5e_dma_info *di,
+ void *va, u16 *rx_headroom, u32 *len)
{
+ const struct bpf_prog *prog = READ_ONCE(rq->xdp_prog);
struct xdp_buff xdp;
u32 act;
if (!prog)
return false;
- xdp.data = data;
- xdp.data_end = xdp.data + len;
+ xdp.data = va + *rx_headroom;
+ xdp.data_end = xdp.data + *len;
+ xdp.data_hard_start = va;
+
act = bpf_prog_run_xdp(prog, &xdp);
switch (act) {
case XDP_PASS:
+ *rx_headroom = xdp.data - xdp.data_hard_start;
+ *len = xdp.data_end - xdp.data;
return false;
case XDP_TX:
- mlx5e_xmit_xdp_frame(rq, di, MLX5_RX_HEADROOM, len);
+ mlx5e_xmit_xdp_frame(rq, di, &xdp);
return true;
default:
bpf_warn_invalid_xdp_action(act);
@@ -740,15 +751,16 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
struct mlx5e_dma_info *di;
struct sk_buff *skb;
void *va, *data;
+ u16 rx_headroom = rq->rx_headroom;
bool consumed;
di = &rq->dma_info[wqe_counter];
va = page_address(di->page);
- data = va + MLX5_RX_HEADROOM;
+ data = va + rx_headroom;
dma_sync_single_range_for_cpu(rq->pdev,
di->addr,
- MLX5_RX_HEADROOM,
+ rx_headroom,
rq->buff.wqe_sz,
DMA_FROM_DEVICE);
prefetch(data);
@@ -760,8 +772,7 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
}
rcu_read_lock();
- consumed = mlx5e_xdp_handle(rq, READ_ONCE(rq->xdp_prog), di, data,
- cqe_bcnt);
+ consumed = mlx5e_xdp_handle(rq, di, va, &rx_headroom, &cqe_bcnt);
rcu_read_unlock();
if (consumed)
return NULL; /* page/packet was consumed by XDP */
@@ -777,7 +788,7 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
page_ref_inc(di->page);
mlx5e_page_release(rq, di, true);
- skb_reserve(skb, MLX5_RX_HEADROOM);
+ skb_reserve(skb, rx_headroom);
skb_put(skb, cqe_bcnt);
return skb;
--
2.5.1
^ permalink raw reply related
* [PATCHv2 iproute2 net-next 2/5] iplink: bridge: add support for IFLA_BR_VLAN_STATS_ENABLED
From: Hangbin Liu @ 2017-01-18 6:12 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
In-Reply-To: <1484719971-21693-1-git-send-email-liuhangbin@gmail.com>
This patch implements support for the IFLA_BR_VLAN_STATS_ENABLED
attribute in iproute2 so it can enable/disable vlan stats accounting.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
ip/iplink_bridge.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 85e6597..cd495b3 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -34,6 +34,7 @@ static void print_explain(FILE *f)
" [ vlan_filtering VLAN_FILTERING ]\n"
" [ vlan_protocol VLAN_PROTOCOL ]\n"
" [ vlan_default_pvid VLAN_DEFAULT_PVID ]\n"
+ " [ vlan_stats_enabled VLAN_STATS_ENABLED ]\n"
" [ mcast_snooping MULTICAST_SNOOPING ]\n"
" [ mcast_router MULTICAST_ROUTER ]\n"
" [ mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR ]\n"
@@ -157,6 +158,14 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
addattr16(n, 1024, IFLA_BR_VLAN_DEFAULT_PVID,
default_pvid);
+ } else if (matches(*argv, "vlan_stats_enabled") == 0) {
+ __u8 vlan_stats_enabled;
+
+ NEXT_ARG();
+ if (get_u8(&vlan_stats_enabled, *argv, 0))
+ invarg("invalid vlan_stats_enabled", *argv);
+ addattr8(n, 1024, IFLA_BR_VLAN_STATS_ENABLED,
+ vlan_stats_enabled);
} else if (matches(*argv, "mcast_router") == 0) {
__u8 mcast_router;
@@ -442,6 +451,10 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
fprintf(f, "vlan_default_pvid %u ",
rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
+ if (tb[IFLA_BR_VLAN_STATS_ENABLED])
+ fprintf(f, "vlan_stats_enabled %u ",
+ rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
+
if (tb[IFLA_BR_GROUP_FWD_MASK])
fprintf(f, "group_fwd_mask %#x ",
rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
--
2.5.5
^ permalink raw reply related
* [PATCHv2 iproute2 net-next 3/5] iplink: bridge: add support for IFLA_BR_MCAST_STATS_ENABLED
From: Hangbin Liu @ 2017-01-18 6:12 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
In-Reply-To: <1484719971-21693-1-git-send-email-liuhangbin@gmail.com>
This patch implements support for the IFLA_BR_MCAST_STATS_ENABLED
attribute in iproute2 so it can enable/disable mcast stats accounting.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
ip/iplink_bridge.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index cd495b3..46bbbee 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -49,6 +49,7 @@ static void print_explain(FILE *f)
" [ mcast_query_interval QUERY_INTERVAL ]\n"
" [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
" [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
+ " [ mcast_stats_enabled MCAST_STATS_ENABLED ]\n"
" [ nf_call_iptables NF_CALL_IPTABLES ]\n"
" [ nf_call_ip6tables NF_CALL_IP6TABLES ]\n"
" [ nf_call_arptables NF_CALL_ARPTABLES ]\n"
@@ -299,6 +300,14 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
addattr64(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
mcast_startup_query_intvl);
+ } else if (matches(*argv, "mcast_stats_enabled") == 0) {
+ __u8 mcast_stats_enabled;
+
+ NEXT_ARG();
+ if (get_u8(&mcast_stats_enabled, *argv, 0))
+ invarg("invalid mcast_stats_enabled", *argv);
+ addattr8(n, 1024, IFLA_BR_MCAST_STATS_ENABLED,
+ mcast_stats_enabled);
} else if (matches(*argv, "nf_call_iptables") == 0) {
__u8 nf_call_ipt;
@@ -524,6 +533,10 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
fprintf(f, "mcast_startup_query_interval %llu ",
rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
+ if (tb[IFLA_BR_MCAST_STATS_ENABLED])
+ fprintf(f, "mcast_stats_enabled %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
+
if (tb[IFLA_BR_NF_CALL_IPTABLES])
fprintf(f, "nf_call_iptables %u ",
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
--
2.5.5
^ permalink raw reply related
* [PATCHv2 iproute2 net-next 0/5] add latest bridge netlink options
From: Hangbin Liu @ 2017-01-18 6:12 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
Add the bridge netlink attributes added to kernel recently.
v2: rename vlan/mcast_state to vlan/mcast_stats_enabled as suggested by
Nikolay. The previous name has different meaning and will mislead people.
I will post a separate patch for IFLA_BRPORT_FLUSH support.
Hangbin Liu (5):
iplink: bridge: add support for IFLA_BR_FDB_FLUSH
iplink: bridge: add support for IFLA_BR_VLAN_STATS_ENABLED
iplink: bridge: add support for IFLA_BR_MCAST_STATS_ENABLED
iplink: bridge: add support for IFLA_BR_MCAST_IGMP_VERSION
iplink: bridge: add support for IFLA_BR_MCAST_MLD_VERSION
ip/iplink_bridge.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
--
2.5.5
^ permalink raw reply
* [PATCHv2 iproute2 net-next 1/5] iplink: bridge: add support for IFLA_BR_FDB_FLUSH
From: Hangbin Liu @ 2017-01-18 6:12 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
In-Reply-To: <1484719971-21693-1-git-send-email-liuhangbin@gmail.com>
This patch implements support for the IFLA_BR_FDB_FLUSH attribute
in iproute2 so it can flush bridge fdb dynamic entries.
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
ip/iplink_bridge.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index d2d4202..85e6597 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -22,7 +22,8 @@
static void print_explain(FILE *f)
{
fprintf(f,
- "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n"
+ "Usage: ... bridge [ fdb_flush ]\n"
+ " [ forward_delay FORWARD_DELAY ]\n"
" [ hello_time HELLO_TIME ]\n"
" [ max_age MAX_AGE ]\n"
" [ ageing_time AGEING_TIME ]\n"
@@ -145,6 +146,8 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
if (len < 0)
return -1;
addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len);
+ } else if (matches(*argv, "fdb_flush") == 0) {
+ addattr(n, 1024, IFLA_BR_FDB_FLUSH);
} else if (matches(*argv, "vlan_default_pvid") == 0) {
__u16 default_pvid;
--
2.5.5
^ permalink raw reply related
* [PATCHv2 iproute2 net-next 5/5] iplink: bridge: add support for IFLA_BR_MCAST_MLD_VERSION
From: Hangbin Liu @ 2017-01-18 6:12 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
In-Reply-To: <1484719971-21693-1-git-send-email-liuhangbin@gmail.com>
This patch implements support for the IFLA_BR_MCAST_MLD_VERSION
attribute in iproute2 so it can change the mcast mld version.
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
ip/iplink_bridge.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 3e9143e..a17ff35 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -51,6 +51,7 @@ static void print_explain(FILE *f)
" [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
" [ mcast_stats_enabled MCAST_STATS_ENABLED ]\n"
" [ mcast_igmp_version IGMP_VERSION ]\n"
+ " [ mcast_mld_version MLD_VERSION ]\n"
" [ nf_call_iptables NF_CALL_IPTABLES ]\n"
" [ nf_call_ip6tables NF_CALL_IP6TABLES ]\n"
" [ nf_call_arptables NF_CALL_ARPTABLES ]\n"
@@ -317,6 +318,14 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
invarg("invalid mcast_igmp_version", *argv);
addattr8(n, 1024, IFLA_BR_MCAST_IGMP_VERSION,
igmp_version);
+ } else if (matches(*argv, "mcast_mld_version") == 0) {
+ __u8 mld_version;
+
+ NEXT_ARG();
+ if (get_u8(&mld_version, *argv, 0))
+ invarg("invalid mcast_mld_version", *argv);
+ addattr8(n, 1024, IFLA_BR_MCAST_MLD_VERSION,
+ mld_version);
} else if (matches(*argv, "nf_call_iptables") == 0) {
__u8 nf_call_ipt;
@@ -550,6 +559,10 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
fprintf(f, "mcast_igmp_version %u ",
rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
+ if (tb[IFLA_BR_MCAST_MLD_VERSION])
+ fprintf(f, "mcast_mld_version %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
+
if (tb[IFLA_BR_NF_CALL_IPTABLES])
fprintf(f, "nf_call_iptables %u ",
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
--
2.5.5
^ permalink raw reply related
* [PATCHv2 iproute2 net-next 4/5] iplink: bridge: add support for IFLA_BR_MCAST_IGMP_VERSION
From: Hangbin Liu @ 2017-01-18 6:12 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
In-Reply-To: <1484719971-21693-1-git-send-email-liuhangbin@gmail.com>
This patch implements support for the IFLA_BR_MCAST_IGMP_VERSION
attribute in iproute2 so it can change the mcast igmp version.
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
ip/iplink_bridge.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 46bbbee..3e9143e 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -50,6 +50,7 @@ static void print_explain(FILE *f)
" [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
" [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
" [ mcast_stats_enabled MCAST_STATS_ENABLED ]\n"
+ " [ mcast_igmp_version IGMP_VERSION ]\n"
" [ nf_call_iptables NF_CALL_IPTABLES ]\n"
" [ nf_call_ip6tables NF_CALL_IP6TABLES ]\n"
" [ nf_call_arptables NF_CALL_ARPTABLES ]\n"
@@ -308,6 +309,14 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
invarg("invalid mcast_stats_enabled", *argv);
addattr8(n, 1024, IFLA_BR_MCAST_STATS_ENABLED,
mcast_stats_enabled);
+ } else if (matches(*argv, "mcast_igmp_version") == 0) {
+ __u8 igmp_version;
+
+ NEXT_ARG();
+ if (get_u8(&igmp_version, *argv, 0))
+ invarg("invalid mcast_igmp_version", *argv);
+ addattr8(n, 1024, IFLA_BR_MCAST_IGMP_VERSION,
+ igmp_version);
} else if (matches(*argv, "nf_call_iptables") == 0) {
__u8 nf_call_ipt;
@@ -537,6 +546,10 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
fprintf(f, "mcast_stats_enabled %u ",
rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
+ if (tb[IFLA_BR_MCAST_IGMP_VERSION])
+ fprintf(f, "mcast_igmp_version %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
+
if (tb[IFLA_BR_NF_CALL_IPTABLES])
fprintf(f, "nf_call_iptables %u ",
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
--
2.5.5
^ permalink raw reply related
* [PATCH iproute2 net-next] iplink: bridge_slave: add support for IFLA_BRPORT_FLUSH
From: Hangbin Liu @ 2017-01-18 6:36 UTC (permalink / raw)
To: netdev; +Cc: Nikolay Aleksandrov, Hangbin Liu
This patch implements support for the IFLA_BRPORT_FLUSH attribute
in iproute2 so it can flush bridge slave's fdb dynamic entries.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
ip/iplink_bridge_slave.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c
index fbb3f06..6353fc5 100644
--- a/ip/iplink_bridge_slave.c
+++ b/ip/iplink_bridge_slave.c
@@ -22,7 +22,10 @@
static void print_explain(FILE *f)
{
fprintf(f,
- "Usage: ... bridge_slave [ state STATE ] [ priority PRIO ] [cost COST ]\n"
+ "Usage: ... bridge_slave [ fdb_flush ]\n"
+ " [ state STATE ]\n"
+ " [ priority PRIO ]\n"
+ " [ cost COST ]\n"
" [ guard {on | off} ]\n"
" [ hairpin {on | off} ]\n"
" [ fastleave {on | off} ]\n"
@@ -217,7 +220,9 @@ static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
__u32 cost;
while (argc > 0) {
- if (matches(*argv, "state") == 0) {
+ if (matches(*argv, "fdb_flush") == 0) {
+ addattr(n, 1024, IFLA_BRPORT_FLUSH);
+ } else if (matches(*argv, "state") == 0) {
NEXT_ARG();
if (get_u8(&state, *argv, 0))
invarg("state is invalid", *argv);
--
2.5.5
^ permalink raw reply related
* [PATCH net-next V5 0/3] vhost_net tx batching
From: Jason Wang @ 2017-01-18 7:02 UTC (permalink / raw)
To: mst, virtualization, netdev, kvm; +Cc: wexu, stefanha
Hi:
This series tries to implement tx batching support for vhost. This was
done by using MSG_MORE as a hint for under layer socket. The backend
(e.g tap) can then batch the packets temporarily in a list and
submit it all once the number of bacthed exceeds a limitation.
Tests shows obvious improvement on guest pktgen over over
mlx4(noqueue) on host:
Mpps -+%
rx-frames = 0 0.91 +0%
rx-frames = 4 1.00 +9.8%
rx-frames = 8 1.00 +9.8%
rx-frames = 16 1.01 +10.9%
rx-frames = 32 1.07 +17.5%
rx-frames = 48 1.07 +17.5%
rx-frames = 64 1.08 +18.6%
rx-frames = 64 (no MSG_MORE) 0.91 +0%
Changes from V4:
- stick to NAPI_POLL_WEIGHT for rx-frames is user specify a value
greater than it.
Changes from V3:
- use ethtool instead of module parameter to control the maximum
number of batched packets
- avoid overhead when MSG_MORE were not set and no packet queued
Changes from V2:
- remove uselss queue limitation check (and we don't drop any packet now)
Changes from V1:
- drop NAPI handler since we don't use NAPI now
- fix the issues that may exceeds max pending of zerocopy
- more improvement on available buffer detection
- move the limitation of batched pacekts from vhost to tuntap
Please review.
Thanks
Jason Wang (3):
vhost: better detection of available buffers
vhost_net: tx batching
tun: rx batching
drivers/net/tun.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++----
drivers/vhost/net.c | 23 ++++++++++++++--
drivers/vhost/vhost.c | 8 ++++--
3 files changed, 96 insertions(+), 11 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH net-next V5 1/3] vhost: better detection of available buffers
From: Jason Wang @ 2017-01-18 7:02 UTC (permalink / raw)
To: mst, virtualization, netdev, kvm; +Cc: wexu, stefanha
In-Reply-To: <1484722923-7698-1-git-send-email-jasowang@redhat.com>
This patch tries to do several tweaks on vhost_vq_avail_empty() for a
better performance:
- check cached avail index first which could avoid userspace memory access.
- using unlikely() for the failure of userspace access
- check vq->last_avail_idx instead of cached avail index as the last
step.
This patch is need for batching supports which needs to peek whether
or not there's still available buffers in the ring.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/vhost/vhost.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index d643260..9f11838 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -2241,11 +2241,15 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)
__virtio16 avail_idx;
int r;
+ if (vq->avail_idx != vq->last_avail_idx)
+ return false;
+
r = vhost_get_user(vq, avail_idx, &vq->avail->idx);
- if (r)
+ if (unlikely(r))
return false;
+ vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
- return vhost16_to_cpu(vq, avail_idx) == vq->avail_idx;
+ return vq->avail_idx == vq->last_avail_idx;
}
EXPORT_SYMBOL_GPL(vhost_vq_avail_empty);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V5 2/3] vhost_net: tx batching
From: Jason Wang @ 2017-01-18 7:02 UTC (permalink / raw)
To: mst, virtualization, netdev, kvm; +Cc: wexu, stefanha
In-Reply-To: <1484722923-7698-1-git-send-email-jasowang@redhat.com>
This patch tries to utilize tuntap rx batching by peeking the tx
virtqueue during transmission, if there's more available buffers in
the virtqueue, set MSG_MORE flag for a hint for backend (e.g tuntap)
to batch the packets.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/vhost/net.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 5dc3465..c42e9c3 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -351,6 +351,15 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
return r;
}
+static bool vhost_exceeds_maxpend(struct vhost_net *net)
+{
+ struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_TX];
+ struct vhost_virtqueue *vq = &nvq->vq;
+
+ return (nvq->upend_idx + vq->num - VHOST_MAX_PEND) % UIO_MAXIOV
+ == nvq->done_idx;
+}
+
/* Expects to be always run from workqueue - which acts as
* read-size critical section for our kind of RCU. */
static void handle_tx(struct vhost_net *net)
@@ -394,8 +403,7 @@ static void handle_tx(struct vhost_net *net)
/* If more outstanding DMAs, queue the work.
* Handle upend_idx wrap around
*/
- if (unlikely((nvq->upend_idx + vq->num - VHOST_MAX_PEND)
- % UIO_MAXIOV == nvq->done_idx))
+ if (unlikely(vhost_exceeds_maxpend(net)))
break;
head = vhost_net_tx_get_vq_desc(net, vq, vq->iov,
@@ -454,6 +462,16 @@ static void handle_tx(struct vhost_net *net)
msg.msg_control = NULL;
ubufs = NULL;
}
+
+ total_len += len;
+ if (total_len < VHOST_NET_WEIGHT &&
+ !vhost_vq_avail_empty(&net->dev, vq) &&
+ likely(!vhost_exceeds_maxpend(net))) {
+ msg.msg_flags |= MSG_MORE;
+ } else {
+ msg.msg_flags &= ~MSG_MORE;
+ }
+
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(sock, &msg, len);
if (unlikely(err < 0)) {
@@ -472,7 +490,6 @@ static void handle_tx(struct vhost_net *net)
vhost_add_used_and_signal(&net->dev, vq, head, 0);
else
vhost_zerocopy_signal_used(net, vq);
- total_len += len;
vhost_net_tx_packet(net);
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V5 3/3] tun: rx batching
From: Jason Wang @ 2017-01-18 7:02 UTC (permalink / raw)
To: mst, virtualization, netdev, kvm; +Cc: wexu, stefanha
In-Reply-To: <1484722923-7698-1-git-send-email-jasowang@redhat.com>
We can only process 1 packet at one time during sendmsg(). This often
lead bad cache utilization under heavy load. So this patch tries to do
some batching during rx before submitting them to host network
stack. This is done through accepting MSG_MORE as a hint from
sendmsg() caller, if it was set, batch the packet temporarily in a
linked list and submit them all once MSG_MORE were cleared.
Tests were done by pktgen (burst=128) in guest over mlx4(noqueue) on host:
Mpps -+%
rx-frames = 0 0.91 +0%
rx-frames = 4 1.00 +9.8%
rx-frames = 8 1.00 +9.8%
rx-frames = 16 1.01 +10.9%
rx-frames = 32 1.07 +17.5%
rx-frames = 48 1.07 +17.5%
rx-frames = 64 1.08 +18.6%
rx-frames = 64 (no MSG_MORE) 0.91 +0%
User were allowed to change per device batched packets through
ethtool -C rx-frames. NAPI_POLL_WEIGHT were used as upper limitation
to prevent bh from being disabled too long.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tun.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 70 insertions(+), 6 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8c1d3bd..13890ac 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -218,6 +218,7 @@ struct tun_struct {
struct list_head disabled;
void *security;
u32 flow_count;
+ u32 rx_batched;
struct tun_pcpu_stats __percpu *pcpu_stats;
};
@@ -522,6 +523,7 @@ static void tun_queue_purge(struct tun_file *tfile)
while ((skb = skb_array_consume(&tfile->tx_array)) != NULL)
kfree_skb(skb);
+ skb_queue_purge(&tfile->sk.sk_write_queue);
skb_queue_purge(&tfile->sk.sk_error_queue);
}
@@ -1139,10 +1141,46 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
return skb;
}
+static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile,
+ struct sk_buff *skb, int more)
+{
+ struct sk_buff_head *queue = &tfile->sk.sk_write_queue;
+ struct sk_buff_head process_queue;
+ u32 rx_batched = tun->rx_batched;
+ bool rcv = false;
+
+ if (!rx_batched || (!more && skb_queue_empty(queue))) {
+ local_bh_disable();
+ netif_receive_skb(skb);
+ local_bh_enable();
+ return;
+ }
+
+ spin_lock(&queue->lock);
+ if (!more || skb_queue_len(queue) == rx_batched) {
+ __skb_queue_head_init(&process_queue);
+ skb_queue_splice_tail_init(queue, &process_queue);
+ rcv = true;
+ } else {
+ __skb_queue_tail(queue, skb);
+ }
+ spin_unlock(&queue->lock);
+
+ if (rcv) {
+ struct sk_buff *nskb;
+
+ local_bh_disable();
+ while ((nskb = __skb_dequeue(&process_queue)))
+ netif_receive_skb(nskb);
+ netif_receive_skb(skb);
+ local_bh_enable();
+ }
+}
+
/* Get packet from user space buffer */
static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
void *msg_control, struct iov_iter *from,
- int noblock)
+ int noblock, bool more)
{
struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
struct sk_buff *skb;
@@ -1283,9 +1321,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
rxhash = skb_get_hash(skb);
#ifndef CONFIG_4KSTACKS
- local_bh_disable();
- netif_receive_skb(skb);
- local_bh_enable();
+ tun_rx_batched(tun, tfile, skb, more);
#else
netif_rx_ni(skb);
#endif
@@ -1311,7 +1347,8 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (!tun)
return -EBADFD;
- result = tun_get_user(tun, tfile, NULL, from, file->f_flags & O_NONBLOCK);
+ result = tun_get_user(tun, tfile, NULL, from,
+ file->f_flags & O_NONBLOCK, false);
tun_put(tun);
return result;
@@ -1569,7 +1606,8 @@ static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
return -EBADFD;
ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter,
- m->msg_flags & MSG_DONTWAIT);
+ m->msg_flags & MSG_DONTWAIT,
+ m->msg_flags & MSG_MORE);
tun_put(tun);
return ret;
}
@@ -1770,6 +1808,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun->align = NET_SKB_PAD;
tun->filter_attached = false;
tun->sndbuf = tfile->socket.sk->sk_sndbuf;
+ tun->rx_batched = 0;
tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
if (!tun->pcpu_stats) {
@@ -2438,6 +2477,29 @@ static void tun_set_msglevel(struct net_device *dev, u32 value)
#endif
}
+static int tun_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ec)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+
+ ec->rx_max_coalesced_frames = tun->rx_batched;
+
+ return 0;
+}
+
+static int tun_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ec)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+
+ if (ec->rx_max_coalesced_frames > NAPI_POLL_WEIGHT)
+ tun->rx_batched = NAPI_POLL_WEIGHT;
+ else
+ tun->rx_batched = ec->rx_max_coalesced_frames;
+
+ return 0;
+}
+
static const struct ethtool_ops tun_ethtool_ops = {
.get_settings = tun_get_settings,
.get_drvinfo = tun_get_drvinfo,
@@ -2445,6 +2507,8 @@ static const struct ethtool_ops tun_ethtool_ops = {
.set_msglevel = tun_set_msglevel,
.get_link = ethtool_op_get_link,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_coalesce = tun_get_coalesce,
+ .set_coalesce = tun_set_coalesce,
};
static int tun_queue_resize(struct tun_struct *tun)
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox