Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 1/2] docs: Add rest label the_canonical_path_format
From: Tobin C. Harding @ 2018-07-25  2:50 UTC (permalink / raw)
  To: David S. Miller, Jonathan Corbet
  Cc: Tobin C. Harding, linux-doc, netdev, linux-kernel
In-Reply-To: <20180725025005.14332-1-me@tobin.cc>

In preparation to convert Documentation/network/netdev-FAQ.rst to
restructured text format we would like to be able to reference 'the
canonical patch format' section.

Add rest label: 'the_canonical_path_format'.

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
 Documentation/process/submitting-patches.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst
index 908bb55be407..c0917107b90a 100644
--- a/Documentation/process/submitting-patches.rst
+++ b/Documentation/process/submitting-patches.rst
@@ -611,6 +611,7 @@ which stable kernel versions should receive your fix. This is the preferred
 method for indicating a bug fixed by the patch. See :ref:`describe_changes`
 for more details.
 
+.. _the_canonical_patch_format:
 
 14) The canonical patch format
 ------------------------------
-- 
2.17.1

^ permalink raw reply related

* [PATCH net-next 0/2] docs: net: Convert netdev-FAQ to RST
From: Tobin C. Harding @ 2018-07-25  2:50 UTC (permalink / raw)
  To: David S. Miller, Jonathan Corbet
  Cc: Tobin C. Harding, linux-doc, netdev, linux-kernel

Jon,

Is it ok for this to go through Dave's tree?  Patch one touches a
line in Documentation/networking/index.rst  Patch two depends on patch
one so it needs to go through the same tree please.


Dave (and Jon),

Kernel docs are prefer restructured text (RST) format.  In doing the
conversion I tried a bunch of different ways to break it up to ease
review.  Nothing I tried worked since so many of the changes touch so
many lines.  In the end I did the whole conversion as a single patch and
listed in the patch commit log each type of change that was made.

Also, with these conversions I'm finding it difficult to split the
changes into separate patches and still keep the tree sane after each
patch.

In an effort to catch mistakes I did the conversion over three days -
there is only so many times you can read a docs file in one day without
your eyes starting to bleed.

Any tips and/or suggestions on making this and future conversions easier
to review much appreciated.  If changes are not widespread it seems to
be better to split the file rename into a separate patch then make the
changes after that.  (For this one it didn't help.)


thanks,
Tobin.

Tobin C. Harding (2):
  docs: Add rest label the_canonical_path_format
  docs: net: Convert netdev-FAQ to restructured text

 Documentation/networking/index.rst           |   1 +
 Documentation/networking/netdev-FAQ.rst      | 259 +++++++++++++++++++
 Documentation/networking/netdev-FAQ.txt      | 244 -----------------
 Documentation/process/submitting-patches.rst |   1 +
 4 files changed, 261 insertions(+), 244 deletions(-)
 create mode 100644 Documentation/networking/netdev-FAQ.rst
 delete mode 100644 Documentation/networking/netdev-FAQ.txt

-- 
2.17.1

^ permalink raw reply

* [PATCH v2] ipvs: fix race between ip_vs_conn_new() and ip_vs_del_dest()
From: Tan Hu @ 2018-07-25  2:49 UTC (permalink / raw)
  To: wensong, horms, ja, pablo, kadlec, fw, davem
  Cc: netdev, lvs-devel, netfilter-devel, coreteam, linux-kernel,
	zhong.weidong, jiang.biao2

We came across infinite loop in ipvs when using ipvs in docker
env.

When ipvs receives new packets and cannot find an ipvs connection,
it will create a new connection, then if the dest is unavailable
(i.e. IP_VS_DEST_F_AVAILABLE), the packet will be dropped sliently.

But if the dropped packet is the first packet of this connection,
the connection control timer never has a chance to start and the
ipvs connection cannot be released. This will lead to memory leak, or
infinite loop in cleanup_net() when net namespace is released like
this:

    ip_vs_conn_net_cleanup at ffffffffa0a9f31a [ip_vs]
    __ip_vs_cleanup at ffffffffa0a9f60a [ip_vs]
    ops_exit_list at ffffffff81567a49
    cleanup_net at ffffffff81568b40
    process_one_work at ffffffff810a851b
    worker_thread at ffffffff810a9356
    kthread at ffffffff810b0b6f
    ret_from_fork at ffffffff81697a18

race condition:
    CPU1                           CPU2
    ip_vs_in()
      ip_vs_conn_new()
                                   ip_vs_del_dest()
                                     __ip_vs_unlink_dest()
                                       ~IP_VS_DEST_F_AVAILABLE
      cp->dest && !IP_VS_DEST_F_AVAILABLE
      __ip_vs_conn_put
    ...
    cleanup_net  ---> infinite looping

Fix this by checking whether the timer already started.

Signed-off-by: Tan Hu <tan.hu@zte.com.cn>
Reviewed-by: Jiang Biao <jiang.biao2@zte.com.cn>
---
v2: fix use-after-free in CONN_ONE_PACKET case suggested by Julian Anastasov

 net/netfilter/ipvs/ip_vs_core.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 0679dd1..a17104f 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1972,13 +1972,20 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
 	if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
 		/* the destination server is not available */
 
-		if (sysctl_expire_nodest_conn(ipvs)) {
+		__u32 flags = cp->flags; 
+
+		/* when timer already started, silently drop the packet.*/
+		if (timer_pending(&cp->timer))
+			__ip_vs_conn_put(cp);
+		else
+			ip_vs_conn_put(cp);
+
+		if (sysctl_expire_nodest_conn(ipvs) &&
+		    !(flags & IP_VS_CONN_F_ONE_PACKET)) {
 			/* try to expire the connection immediately */
 			ip_vs_conn_expire_now(cp);
 		}
-		/* don't restart its timer, and silently
-		   drop the packet. */
-		__ip_vs_conn_put(cp);
+
 		return NF_DROP;
 	}
 
-- 
1.8.3.1

^ permalink raw reply related

* Re: Re: [PATCH] ipvs: fix race between ip_vs_conn_new() andip_vs_del_dest()
From: tan.hu @ 2018-07-25  2:46 UTC (permalink / raw)
  To: ja
  Cc: wensong, horms, pablo, kadlec, fw, davem, netdev, lvs-devel,
	netfilter-devel, coreteam, linux-kernel, zhong.weidong,
	jiang.biao2
In-Reply-To: <alpine.LFD.2.20.1807242216100.3314@ja.home.ssi.bg>


[-- Attachment #1.1: Type: text/plain, Size: 2909 bytes --]

Thanks for your reviewing, I have sent patch-v2, please check it.

> Hello,
> 
> On Tue, 24 Jul 2018, Tan Hu wrote:
> 
> > We came across infinite loop in ipvs when using ipvs in docker
> > env.
> >
> > When ipvs receives new packets and cannot find an ipvs connection,
> > it will create a new connection, then if the dest is unavailable
> > (i.e. IP_VS_DEST_F_AVAILABLE), the packet will be dropped sliently.
> >
> > But if the dropped packet is the first packet of this connection,
> > the connection control timer never has a chance to start and the
> > ipvs connection cannot be released. This will lead to memory leak, or
> > infinite loop in cleanup_net() when net namespace is released like
> > this:
> >
> > ip_vs_conn_net_cleanup at ffffffffa0a9f31a [ip_vs]
> > __ip_vs_cleanup at ffffffffa0a9f60a [ip_vs]
> > ops_exit_list at ffffffff81567a49
> > cleanup_net at ffffffff81568b40
> > process_one_work at ffffffff810a851b
> > worker_thread at ffffffff810a9356
> > kthread at ffffffff810b0b6f
> > ret_from_fork at ffffffff81697a18
> >
> > race condition:
> > CPU1 CPU2
> > ip_vs_in()
> > ip_vs_conn_new()
> > ip_vs_del_dest()
> > __ip_vs_unlink_dest()
> > ~IP_VS_DEST_F_AVAILABLE
> > cp->dest && !IP_VS_DEST_F_AVAILABLE
> > __ip_vs_conn_put
> > ...
> > cleanup_net ---> infinite looping
> >
> > Fix this by checking whether the timer already started.
> 
> Looks like an old bug...
> 
> >
> > Signed-off-by: Tan Hu <tan.hu@zte.com.cn>
> > Reviewed-by: Jiang Biao <jiang.biao2@zte.com.cn>
> > ---
> > net/netfilter/ipvs/ip_vs_core.c | 10 +++++++---
> > 1 file changed, 7 insertions(+), 3 deletions(-)
> >
> > diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> > index 0679dd1..ca9e7cc 100644
> > --- a/net/netfilter/ipvs/ip_vs_core.c
> > +++ b/net/netfilter/ipvs/ip_vs_core.c
> > @@ -1972,13 +1972,17 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
> > if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
> > /* the destination server is not available */
> 
> Add: u32 flags = cp->flags;
> 
> >
> > + /* when timer already started, silently drop the packet.*/
> > + if (timer_pending(&cp->timer))
> > + __ip_vs_conn_put(cp);
> > + else
> > + ip_vs_conn_put(cp);
> 
> When ip_vs_conn_put is called for IP_VS_CONN_F_ONE_PACKET
> it is possible to call ip_vs_conn_expire and to free cp with
> ip_vs_conn_rcu_free immediately. What we can do is to avoid the
> ip_vs_conn_expire_now call in such case by reading the flags
> early (as above) and adding the needed check (as below).
> 
> > +
> > if (sysctl_expire_nodest_conn(ipvs)) {
> 
> Add !(flags & IP_VS_CONN_F_ONE_PACKET) check in above 'if'.
> 
> > /* try to expire the connection immediately */
> > ip_vs_conn_expire_now(cp);
> > }
> > - /* don't restart its timer, and silently
> > - drop the packet. */
> > - __ip_vs_conn_put(cp);
> > +
> > return NF_DROP;
> > }
> >
> 
> Regards

^ permalink raw reply

* [PATCH 4/4] docs: bpf: Capitalise document heading
From: Tobin C. Harding @ 2018-07-25  2:29 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Tobin C. Harding, Alexei Starovoitov, Daniel Borkmann, linux-doc,
	netdev, linux-kernel
In-Reply-To: <20180725022926.8993-1-me@tobin.cc>

The majority of files in the kernel documentation index use
capitalisation for all words, especially the shorter ones.  BPF docs
better fit in with the rest of the documentation if the heading is all
capitalised.

Capitalise document heading.

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
 Documentation/bpf/index.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst
index ab2ff13a809b..00a8450a602f 100644
--- a/Documentation/bpf/index.rst
+++ b/Documentation/bpf/index.rst
@@ -1,5 +1,5 @@
 =================
-BPF documentation
+BPF Documentation
 =================
 
 This directory contains documentation for the BPF (Berkeley Packet
-- 
2.17.1

^ permalink raw reply related

* [PATCH 3/4] docs: Add bpf/index to top level index
From: Tobin C. Harding @ 2018-07-25  2:29 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Tobin C. Harding, Alexei Starovoitov, Daniel Borkmann, linux-doc,
	netdev, linux-kernel
In-Reply-To: <20180725022926.8993-1-me@tobin.cc>

Recently bpf docs were converted to RST format.  The new files were not
added to the top level toctree.  This causes build system to emit a
warning of type

	WARNING: document isn't included in any toctree

Add bpf/index.rst to Documentation/index.rst

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
 Documentation/index.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/index.rst b/Documentation/index.rst
index 5d310d960f82..24339a9c2ef8 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -92,6 +92,7 @@ needed).
    crypto/index
    filesystems/index
    vm/index
+   bpf/index
 
 Architecture-specific documentation
 -----------------------------------
-- 
2.17.1

^ permalink raw reply related

* [PATCH 2/4] docs: bpf: Add toctree to index
From: Tobin C. Harding @ 2018-07-25  2:29 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Tobin C. Harding, Alexei Starovoitov, Daniel Borkmann, linux-doc,
	netdev, linux-kernel
In-Reply-To: <20180725022926.8993-1-me@tobin.cc>

Recently bpf/ docs were converted to us RST format.  bp/index.rst was
created out of README but toctree was not added to include files within
Documentation/bpf/

Add toctree to Documentation/bpf/index.rst

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
 Documentation/bpf/index.rst | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst
index b9a80c9e9392..ab2ff13a809b 100644
--- a/Documentation/bpf/index.rst
+++ b/Documentation/bpf/index.rst
@@ -22,14 +22,14 @@ Frequently asked questions (FAQ)
 
 Two sets of Questions and Answers (Q&A) are maintained.
 
-* QA for common questions about BPF see: bpf_design_QA_
+.. toctree::
+   :maxdepth: 1
 
-* QA for developers interacting with BPF subsystem: bpf_devel_QA_
+   bpf_design_QA
+   bpf_devel_QA
 
 
 .. Links:
-.. _bpf_design_QA: bpf_design_QA.rst
-.. _bpf_devel_QA:  bpf_devel_QA.rst
 .. _Documentation/networking/filter.txt: ../networking/filter.txt
 .. _man-pages: https://www.kernel.org/doc/man-pages/
 .. _bpf(2): http://man7.org/linux/man-pages/man2/bpf.2.html
-- 
2.17.1

^ permalink raw reply related

* [PATCH 1/4] docs: bpf: Rename README.rst to index.rst
From: Tobin C. Harding @ 2018-07-25  2:29 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Tobin C. Harding, Alexei Starovoitov, Daniel Borkmann, linux-doc,
	netdev, linux-kernel
In-Reply-To: <20180725022926.8993-1-me@tobin.cc>

Recently bpf/ docs were converted to us RST format.  'README.rst' was
created but in order to fit in with the Sphinx build system this file
should be named 'index.rst'.  Rename file, fixes to integrate into Sphinx
build system in following patches.

docs: Rename Documentation/bpf/README.rst to Documentation/bpf/index.rst

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
 Documentation/bpf/{README.rst => index.rst} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/bpf/{README.rst => index.rst} (100%)

diff --git a/Documentation/bpf/README.rst b/Documentation/bpf/index.rst
similarity index 100%
rename from Documentation/bpf/README.rst
rename to Documentation/bpf/index.rst
-- 
2.17.1

^ permalink raw reply

* [PATCH 0/4] docs: bpf: Fix RST conversion
From: Tobin C. Harding @ 2018-07-25  2:29 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Tobin C. Harding, Alexei Starovoitov, Daniel Borkmann, linux-doc,
	netdev, linux-kernel

Recently BPF docs were converted to RST format.  A couple of things were
missed.

 - Use 'index.rst' instead of 'README.rst'.  Although README.rst will
   work just fine it is more typical to keep the subdirectory indices
   in a file called 'index.rst'.

 - Integrate files Documentation/bpf/*.rst into build system using
   toctree in Documentation/bpf/index.rst

 - Include bpf/index in top level toctree so bpf is indexed in the main
   kernel docs.

 - Make anal change to heading format (inline with rest of Documentation/).

thanks,
Tobin.


Tobin C. Harding (4):
  docs: bpf: Rename README.rst to index.rst
  docs: bpf: Add toctree to index
  docs: Add bpf/index to top level index
  docs: bpf: Capitalise document heading

 Documentation/bpf/{README.rst => index.rst} | 10 +++++-----
 Documentation/index.rst                     |  1 +
 2 files changed, 6 insertions(+), 5 deletions(-)
 rename Documentation/bpf/{README.rst => index.rst} (82%)

-- 
2.17.1

^ permalink raw reply

* Re: [PATCH net-next 0/6] virtio_net: Add ethtool stat items
From: David Miller @ 2018-07-25  2:06 UTC (permalink / raw)
  To: toshiaki.makita1; +Cc: netdev, virtualization, mst
In-Reply-To: <20180723143609.2242-1-toshiaki.makita1@gmail.com>

From: Toshiaki Makita <toshiaki.makita1@gmail.com>
Date: Mon, 23 Jul 2018 23:36:03 +0900

> From: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
> 
> Add some ethtool stat items useful for performance analysis.
> 
> Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>

Michael and Jason, any objections to these new stats?

^ permalink raw reply

* Re: [PATCH 1/4] treewide: convert ISO_8859-1 text comments to utf-8
From: Andrew Morton @ 2018-07-25  0:55 UTC (permalink / raw)
  To: Joe Perches
  Cc: Arnd Bergmann, Samuel Ortiz, David S. Miller, Rob Herring,
	Michael Ellerman, Jonathan Cameron, linux-wireless, netdev,
	devicetree, linux-kernel, linux-arm-kernel, linux-crypto,
	linuxppc-dev, linux-iio, linux-pm, lvs-devel, netfilter-devel,
	coreteam
In-Reply-To: <aa39b6d15f44555cb79d5ebdef74aeab19003d6a.camel@perches.com>

On Tue, 24 Jul 2018 17:13:20 -0700 Joe Perches <joe@perches.com> wrote:

> On Tue, 2018-07-24 at 14:00 -0700, Andrew Morton wrote:
> > On Tue, 24 Jul 2018 13:13:25 +0200 Arnd Bergmann <arnd@arndb.de> wrote:
> > > Almost all files in the kernel are either plain text or UTF-8
> > > encoded. A couple however are ISO_8859-1, usually just a few
> > > characters in a C comments, for historic reasons.
> > > This converts them all to UTF-8 for consistency.
> []
> > Will we be getting a checkpatch rule to keep things this way?
> 
> How would that be done?

I'm using this, seems to work.

        if ! file $p | grep -q -P ", ASCII text|, UTF-8 Unicode text"
        then
                echo $p: weird charset
        fi

^ permalink raw reply

* Re: selftests/bpf test_sockmap failure
From: Prashant Bhole @ 2018-07-25  0:49 UTC (permalink / raw)
  To: Yonghong Song, John Fastabend, netdev; +Cc: Martin Lau
In-Reply-To: <46dfed54-3634-af7a-2b14-b64b5d33a8e8@fb.com>



On 7/25/2018 8:02 AM, Yonghong Song wrote:
> 
> 
> On 7/24/18 3:40 PM, John Fastabend wrote:
>> On 07/24/2018 08:45 AM, Yonghong Song wrote:
>>> In one of our production machines, tools/testing/selftests/bpf
>>> test_sockmap failed randomly like below:
>>>
>>> ...
>>> [TEST 78]: (512, 1, 1, sendmsg, pass,apply 1,): rx thread exited with
>>> err 1. FAILED
>>> ...
>>>
>>> ...
>>> [TEST 80]: (2, 1024, 256, sendmsg, pass,apply 1,): rx thread exited with
>>> err 1. FAILED
>>> ...
>>>
>>> ...
>>> [TEST 83]: (100, 1, 5, sendpage, pass,apply 1,): rx thread exited with
>>> err 1. FAILED
>>> ...
>>>
>>> ...
>>> [TEST 79]: (512, 1, 1, sendpage, pass,apply 1,): rx thread exited with
>>> err 1. FAILED
>>> ...
>>>
>>> The command line is just `test_sockmap`. The machine has 80 cpus, 256G
>>> memory. The kernel is based on 4.16 but backported with latest bpf-next
>>> bpf changes.
>>>
>>> The failed test number (78, 79, 80, or 83) is random. But they all share
>>> similar characteristics:
>>>     . the option rate is greater than one, i.e., more than one
>>>       sendmsg/sendpage in the sender forked process.
>>>     . The txmsg_apply is not 0
>>>
>>> I debugged a little bit. It happens in msg_loop() function below
>>> "unexpected timeout" path.
>>>
>>> ...
>>>                          slct = select(max_fd + 1, &w, NULL, NULL,
>>> &timeout);
>>>                          if (slct == -1) {
>>>                                  perror("select()");
>>>                                  clock_gettime(CLOCK_MONOTONIC, 
>>> &s->end);
>>>                                  goto out_errno;
>>>                          } else if (!slct) {
>>>                                  if (opt->verbose)
>>>                                          fprintf(stderr, "unexpected
>>> timeout\n");
>>>                                  errno = -EIO;
>>>                                  clock_gettime(CLOCK_MONOTONIC, 
>>> &s->end);
>>>                                  goto out_errno;
>>>                          }
>>> ...
>>>
>>> It appears that when the error happens, the receive process does not
>>> receive all bytes sent from the send process and eventually times out.
>>>
>>> Has anybody seen this issue as well?
>>> John, any comments on this failure?
>>
>> Can you run the test with verbose enabled so we can determine if the tx
>> side is even sending the message? Sample patch below. This will allow
>> us to see the tx bytes and rx bytes, although it will be a bit noisy.
>>
>> I notice that the test program is not smart enough to (re)send bytes if
>> the sendmsg call doesn't consume all bytes. This is a valid error if
>> we get a enomem or other normal error on the tx side. With apply this
>> is more likely because every byte (in apply = 1 case) is being sent
>> through BPF prog.
> 
> The following are some of logs for the failed tests:
> 
> ...
> [TEST 78]: (512, 1, 1, sendmsg, pass,apply 1,): connected sockets: c1 
> <-> p1, c2 <-> p2
> cgroups binding: c1(24) <-> s1(22) - - - c2(25) <-> s2(23)
> tx_sendmsg: TX: 512B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
> 0.000000GB/s
> unexpected timeout
> msg_loop_rx: iov_count 1 iov_buf 1 cnt 512 err -5
> rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 147B 147.000000B/s 
> 0.000000GB/s
> rx thread exited with err 1. FAILED
> ...
> 
> [TEST 82]: (100, 1, 5, sendmsg, pass,apply 1,): connected sockets: c1 
> <-> p1, c2 <-> p2
> cgroups binding: c1(24) <-> s1(22) - - - c2(25) <-> s2(23)
> tx_sendmsg: TX: 500B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
> 0.000000GB/s
> unexpected timeout
> msg_loop_rx: iov_count 1 iov_buf 5 cnt 100 err -5
> rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 366B 366.000000B/s 
> 0.000000GB/s
> rx thread exited with err 1. FAILED
> 
> [TEST 402]: (512, 1, 1, sendmsg, pass,apply 1,): connected sockets: c1 
> <-> p1, c2 <-> p2
> cgroups binding: c1(42) <-> s1(40) - - - c2(43) <-> s2(41)
> tx_sendmsg: TX: 512B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
> 0.000000GB/s
> unexpected timeout
> msg_loop_rx: iov_count 1 iov_buf 1 cnt 512 err -5
> rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 147B 147.000000B/s 
> 0.000000GB/s
> rx thread exited with err 1. FAILED
> 
> [TEST 80]: (2, 1024, 256, sendmsg, pass,apply 1,): connected sockets: c1 
> <-> p1, c2 <-> p2
> cgroups binding: c1(24) <-> s1(22) - - - c2(25) <-> s2(23)
> tx_sendmsg: TX: 524288B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
> 0.000000GB/s
> unexpected timeout
> msg_loop_rx: iov_count 1024 iov_buf 256 cnt 2 err -5
> rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 458805B 458805.000000B/s 
> 0.000459GB/s
> rx thread exited with err 1. FAILED
> 
> 
>>
>> If this is not the case I can do some more digging but I've not seen
>> this before.
> 
> I cannot reproduce it in my FC27 VM (with latest bpf-next) either.
> The bug only shows up on our production service which is a lot busier 
> and has more cpus/memorys and some sysctl configurations are different 
> from my VM setup.

In the past I have noticed that on busy machines sometimes data is 
delayed so much that select() timeout is triggered. Although it isn't a 
solution but you can try to increase the timeout value to check if that 
is the case.

-Prashant

^ permalink raw reply

* Re: [net-next V2 12/12] net/mlx5e: Use PARTIAL_GSO for UDP segmentation
From: Saeed Mahameed @ 2018-07-25  0:35 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: Saeed Mahameed, David S. Miller, Netdev, Boris Pismenny
In-Reply-To: <CAKgT0UcdnUWgr3KQ=RnLKigokkiUuYefmL-ePpDvJOBNpKScFA@mail.gmail.com>

On Tue, Jul 24, 2018 at 7:53 AM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Mon, Jul 23, 2018 at 3:11 PM, Saeed Mahameed <saeedm@mellanox.com> wrote:
>> From: Boris Pismenny <borisp@mellanox.com>
>>
>> This patch removes the splitting of UDP_GSO_L4 packets in the driver,
>> and exposes UDP_GSO_L4 as a PARTIAL_GSO feature. Thus, the network stack
>> is not responsible for splitting the packet into two.
>>
>> Signed-off-by: Boris Pismenny <borisp@mellanox.com>
>> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
>> ---
>>  .../net/ethernet/mellanox/mlx5/core/Makefile  |   4 +-
>>  .../mellanox/mlx5/core/en_accel/en_accel.h    |  27 +++--
>>  .../mellanox/mlx5/core/en_accel/rxtx.c        | 109 ------------------
>>  .../mellanox/mlx5/core/en_accel/rxtx.h        |  14 ---
>>  .../net/ethernet/mellanox/mlx5/core/en_main.c |   9 +-
>>  5 files changed, 23 insertions(+), 140 deletions(-)
>>  delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.c
>>  delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.h
>>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> index 55d5a5c2e9d8..fa7fcca5dc78 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> @@ -14,8 +14,8 @@ mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o \
>>                 fpga/ipsec.o fpga/tls.o
>>
>>  mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
>> -               en_tx.o en_rx.o en_dim.o en_txrx.o en_accel/rxtx.o en_stats.o  \
>> -               vxlan.o en_arfs.o en_fs_ethtool.o en_selftest.o en/port.o
>> +               en_tx.o en_rx.o en_dim.o en_txrx.o en_stats.o vxlan.o          \
>> +               en_arfs.o en_fs_ethtool.o en_selftest.o en/port.o
>>
>>  mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
>>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
>> index 39a5d13ba459..1dd225380a66 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
>> @@ -38,14 +38,22 @@
>>  #include <linux/netdevice.h>
>>  #include "en_accel/ipsec_rxtx.h"
>>  #include "en_accel/tls_rxtx.h"
>> -#include "en_accel/rxtx.h"
>>  #include "en.h"
>>
>> -static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
>> -                                                   struct mlx5e_txqsq *sq,
>> -                                                   struct net_device *dev,
>> -                                                   struct mlx5e_tx_wqe **wqe,
>> -                                                   u16 *pi)
>> +static inline void
>> +mlx5e_udp_gso_handle_tx_skb(struct sk_buff *skb)
>> +{
>> +       int payload_len = skb_shinfo(skb)->gso_size + sizeof(struct udphdr);
>> +
>> +       udp_hdr(skb)->len = htons(payload_len);
>> +}
>> +
>
> So it looks like you decided to just update the length here. Do you
> still have plans to update GSO_PARTIAL to set the length this way or
> have you decided to just leave it as it is?
>

I don't know what are Boris's plans regarding this, I will let him answer that.
But what is your take on this ?

>> +static inline struct sk_buff *
>> +mlx5e_accel_handle_tx(struct sk_buff *skb,
>> +                     struct mlx5e_txqsq *sq,
>> +                     struct net_device *dev,
>> +                     struct mlx5e_tx_wqe **wqe,
>> +                     u16 *pi)
>>  {
>>  #ifdef CONFIG_MLX5_EN_TLS
>>         if (test_bit(MLX5E_SQ_STATE_TLS, &sq->state)) {
>> @@ -63,11 +71,8 @@ static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
>>         }
>>  #endif
>>
>> -       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
>> -               skb = mlx5e_udp_gso_handle_tx_skb(dev, sq, skb, wqe, pi);
>> -               if (unlikely(!skb))
>> -                       return NULL;
>> -       }
>> +       if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
>> +               mlx5e_udp_gso_handle_tx_skb(skb);
>>
>>         return skb;
>>  }
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.c
>> deleted file mode 100644
>> index 7b7ec3998e84..000000000000
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.c
>> +++ /dev/null
>> @@ -1,109 +0,0 @@
>> -#include "en_accel/rxtx.h"
>> -
>> -static void mlx5e_udp_gso_prepare_last_skb(struct sk_buff *skb,
>> -                                          struct sk_buff *nskb,
>> -                                          int remaining)
>> -{
>> -       int bytes_needed = remaining, remaining_headlen, remaining_page_offset;
>> -       int headlen = skb_transport_offset(skb) + sizeof(struct udphdr);
>> -       int payload_len = remaining + sizeof(struct udphdr);
>> -       int k = 0, i, j;
>> -
>> -       skb_copy_bits(skb, 0, nskb->data, headlen);
>> -       nskb->dev = skb->dev;
>> -       skb_reset_mac_header(nskb);
>> -       skb_set_network_header(nskb, skb_network_offset(skb));
>> -       skb_set_transport_header(nskb, skb_transport_offset(skb));
>> -       skb_set_tail_pointer(nskb, headlen);
>> -
>> -       /* How many frags do we need? */
>> -       for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) {
>> -               bytes_needed -= skb_frag_size(&skb_shinfo(skb)->frags[i]);
>> -               k++;
>> -               if (bytes_needed <= 0)
>> -                       break;
>> -       }
>> -
>> -       /* Fill the first frag and split it if necessary */
>> -       j = skb_shinfo(skb)->nr_frags - k;
>> -       remaining_page_offset = -bytes_needed;
>> -       skb_fill_page_desc(nskb, 0,
>> -                          skb_shinfo(skb)->frags[j].page.p,
>> -                          skb_shinfo(skb)->frags[j].page_offset + remaining_page_offset,
>> -                          skb_shinfo(skb)->frags[j].size - remaining_page_offset);
>> -
>> -       skb_frag_ref(skb, j);
>> -
>> -       /* Fill the rest of the frags */
>> -       for (i = 1; i < k; i++) {
>> -               j = skb_shinfo(skb)->nr_frags - k + i;
>> -
>> -               skb_fill_page_desc(nskb, i,
>> -                                  skb_shinfo(skb)->frags[j].page.p,
>> -                                  skb_shinfo(skb)->frags[j].page_offset,
>> -                                  skb_shinfo(skb)->frags[j].size);
>> -               skb_frag_ref(skb, j);
>> -       }
>> -       skb_shinfo(nskb)->nr_frags = k;
>> -
>> -       remaining_headlen = remaining - skb->data_len;
>> -
>> -       /* headlen contains remaining data? */
>> -       if (remaining_headlen > 0)
>> -               skb_copy_bits(skb, skb->len - remaining, nskb->data + headlen,
>> -                             remaining_headlen);
>> -       nskb->len = remaining + headlen;
>> -       nskb->data_len =  payload_len - sizeof(struct udphdr) +
>> -               max_t(int, 0, remaining_headlen);
>> -       nskb->protocol = skb->protocol;
>> -       if (nskb->protocol == htons(ETH_P_IP)) {
>> -               ip_hdr(nskb)->id = htons(ntohs(ip_hdr(nskb)->id) +
>> -                                        skb_shinfo(skb)->gso_segs);
>> -               ip_hdr(nskb)->tot_len =
>> -                       htons(payload_len + sizeof(struct iphdr));
>> -       } else {
>> -               ipv6_hdr(nskb)->payload_len = htons(payload_len);
>> -       }
>> -       udp_hdr(nskb)->len = htons(payload_len);
>> -       skb_shinfo(nskb)->gso_size = 0;
>> -       nskb->ip_summed = skb->ip_summed;
>> -       nskb->csum_start = skb->csum_start;
>> -       nskb->csum_offset = skb->csum_offset;
>> -       nskb->queue_mapping = skb->queue_mapping;
>> -}
>> -
>> -/* might send skbs and update wqe and pi */
>> -struct sk_buff *mlx5e_udp_gso_handle_tx_skb(struct net_device *netdev,
>> -                                           struct mlx5e_txqsq *sq,
>> -                                           struct sk_buff *skb,
>> -                                           struct mlx5e_tx_wqe **wqe,
>> -                                           u16 *pi)
>> -{
>> -       int payload_len = skb_shinfo(skb)->gso_size + sizeof(struct udphdr);
>> -       int headlen = skb_transport_offset(skb) + sizeof(struct udphdr);
>> -       int remaining = (skb->len - headlen) % skb_shinfo(skb)->gso_size;
>> -       struct sk_buff *nskb;
>> -
>> -       if (skb->protocol == htons(ETH_P_IP))
>> -               ip_hdr(skb)->tot_len = htons(payload_len + sizeof(struct iphdr));
>> -       else
>> -               ipv6_hdr(skb)->payload_len = htons(payload_len);
>> -       udp_hdr(skb)->len = htons(payload_len);
>> -       if (!remaining)
>> -               return skb;
>> -
>> -       sq->stats->udp_seg_rem++;
>> -       nskb = alloc_skb(max_t(int, headlen, headlen + remaining - skb->data_len), GFP_ATOMIC);
>> -       if (unlikely(!nskb)) {
>> -               sq->stats->dropped++;
>> -               return NULL;
>> -       }
>> -
>> -       mlx5e_udp_gso_prepare_last_skb(skb, nskb, remaining);
>> -
>> -       skb_shinfo(skb)->gso_segs--;
>> -       pskb_trim(skb, skb->len - remaining);
>> -       mlx5e_sq_xmit(sq, skb, *wqe, *pi);
>> -       mlx5e_sq_fetch_wqe(sq, wqe, pi);
>> -       return nskb;
>> -}
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.h
>> deleted file mode 100644
>> index ed42699a78b3..000000000000
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/rxtx.h
>> +++ /dev/null
>> @@ -1,14 +0,0 @@
>> -
>> -#ifndef __MLX5E_EN_ACCEL_RX_TX_H__
>> -#define __MLX5E_EN_ACCEL_RX_TX_H__
>> -
>> -#include <linux/skbuff.h>
>> -#include "en.h"
>> -
>> -struct sk_buff *mlx5e_udp_gso_handle_tx_skb(struct net_device *netdev,
>> -                                           struct mlx5e_txqsq *sq,
>> -                                           struct sk_buff *skb,
>> -                                           struct mlx5e_tx_wqe **wqe,
>> -                                           u16 *pi);
>> -
>> -#endif
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
>> index 712b9766485f..dccde18f6170 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
>> @@ -4538,7 +4538,6 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
>>         netdev->hw_features      |= NETIF_F_HW_VLAN_STAG_TX;
>>
>>         if (mlx5e_vxlan_allowed(mdev) || MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
>> -               netdev->hw_features     |= NETIF_F_GSO_PARTIAL;
>>                 netdev->hw_enc_features |= NETIF_F_IP_CSUM;
>>                 netdev->hw_enc_features |= NETIF_F_IPV6_CSUM;
>>                 netdev->hw_enc_features |= NETIF_F_TSO;
>> @@ -4563,6 +4562,11 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
>>                                                 NETIF_F_GSO_GRE_CSUM;
>>         }
>>
>> +       netdev->hw_features                      |= NETIF_F_GSO_PARTIAL;
>> +       netdev->gso_partial_features             |= NETIF_F_GSO_UDP_L4;
>> +       netdev->hw_features                      |= NETIF_F_GSO_UDP_L4;
>> +       netdev->features                         |= NETIF_F_GSO_UDP_L4;
>> +
>
> Isn't the setting of netdev->features going to be overwritten when you
> do the "netdev->features = netdev->hw_features" assignment a little
> further down in the function?
>

Yes, nice catch, the line "netdev->features |= NETIF_F_GSO_UDP_L4;"
above is redundant.
we will clean it up later.

Thanks Alex!

>>         mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled);
>>
>>         if (fcs_supported)
>> @@ -4595,9 +4599,6 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
>>         netdev->features         |= NETIF_F_HIGHDMA;
>>         netdev->features         |= NETIF_F_HW_VLAN_STAG_FILTER;
>>
>> -       netdev->features         |= NETIF_F_GSO_UDP_L4;
>> -       netdev->hw_features      |= NETIF_F_GSO_UDP_L4;
>> -
>>         netdev->priv_flags       |= IFF_UNICAST_FLT;
>>
>>         mlx5e_set_netdev_dev_addr(netdev);
>> --
>> 2.17.0
>>

^ permalink raw reply

* Re: [PATCH bpf] bpf: Use option "help" in the llvm-objcopy test
From: Yonghong Song @ 2018-07-25  0:30 UTC (permalink / raw)
  To: Daniel Borkmann, Martin KaFai Lau, netdev; +Cc: Alexei Starovoitov, kernel-team
In-Reply-To: <34e16aab-db8b-ef38-4c56-6bbf6e81f673@iogearbox.net>



On 7/20/18 1:37 AM, Daniel Borkmann wrote:
> On 07/20/2018 07:34 AM, Martin KaFai Lau wrote:
>> I noticed the "--version" option of the llvm-objcopy command has recently
>> disappeared from the master llvm branch.  It is currently used as a BTF
>> support test in tools/testing/selftests/bpf/Makefile.
>>
>> This patch replaces it with "--help" which should be
>> less error prone in the future.
>>
>> Fixes: c0fa1b6c3efc ("bpf: btf: Add BTF tests")
>> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> 
> Looks good, ran into the same recently as well from llvm git. Wondering whether
> the "--version" removal there was by accident or on purpose. In any case, applied

The option "--version" seems removed by accident.
On 6.0.0, the option handling is done by llvm.
      static cl::opt<std::string>
              OutputFormat("O", cl::desc("Set output format to one of the
                           following:"
                           "\n\tbinary"));
      cl::ParseCommandLineOptions(argc, argv, "llvm objcopy utility\n");
That is, the options are defined through llvm option handling system and
option "--version" is handled by llvm automatically.

In 7.0.0, llvm-objcopy tries to handle the options itself. 
Unfortunately, it did not define "version" option in its option file, so
"llvm-objcopy --version" won't work any more.

I will raise a bug or fix the issue properly.

> to bpf tree, thanks! If we make another change to the Makefile in near future,
> we should also make a comment there that the llvm-objcopy is used by pahole -J
> internally to make it a bit more clear in case someone is wondering why it's not
> used in the Makefile itself.
> 
> Thanks,
> Daniel
> 

^ permalink raw reply

* Re: [PATCH net-next] virtio_net: force_napi_tx module param.
From: Jon Olson @ 2018-07-25  0:17 UTC (permalink / raw)
  To: mst
  Cc: willemdebruijn.kernel, caleb.raitto, jasowang, davem, netdev,
	Caleb Raitto
In-Reply-To: <20180725014410-mutt-send-email-mst@kernel.org>

On Tue, Jul 24, 2018 at 3:46 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Tue, Jul 24, 2018 at 06:31:54PM -0400, Willem de Bruijn wrote:
> > On Tue, Jul 24, 2018 at 6:23 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > >
> > > On Tue, Jul 24, 2018 at 04:52:53PM -0400, Willem de Bruijn wrote:
> > > > >From the above linked patch, I understand that there are yet
> > > > other special cases in production, such as a hard cap on #tx queues to
> > > > 32 regardless of number of vcpus.
> > >
> > > I don't think upstream kernels have this limit - we can
> > > now use vmalloc for higher number of queues.
> >
> > Yes. that patch* mentioned it as a google compute engine imposed
> > limit. It is exactly such cloud provider imposed rules that I'm
> > concerned about working around in upstream drivers.
> >
> > * for reference, I mean https://patchwork.ozlabs.org/patch/725249/
>
> Yea. Why does GCE do it btw?

There are a few reasons for the limit, some historical, some current.

Historically we did this because of a kernel limit on the number of
TAP queues (in Montreal I thought this limit was 32). To my chagrin,
the limit upstream at the time we did it was actually eight. We had
increased the limit from eight to 32 internally, and it appears in
upstream it has subsequently increased upstream to 256. We no longer
use TAP for networking, so that constraint no longer applies for us,
but when looking at removing/raising the limit we discovered no
workloads that clearly benefited from lifting it, and it also placed
more pressure on our virtual networking stack particularly on the Tx
side. We left it as-is.

In terms of current reasons there are really two. One is memory usage.
As you know, virtio-net uses rx/tx pairs, so there's an expectation
that the guest will have an Rx queue for every Tx queue. We run our
individual virtqueues fairly deep (4096 entries) to give guests a wide
time window for re-posting Rx buffers and avoiding starvation on
packet delivery. Filling an Rx vring with max-sized mergeable buffers
(4096 bytes) is 16MB of GFP_ATOMIC allocations. At 32 queues this can
be up to 512MB of memory posted for network buffers. Scaling this to
the largest VM GCE offers today (160 VCPUs -- n1-ultramem-160) keeping
all of the Rx rings full would (in the large average Rx packet size
case) consume up to 2.5 GB(!) of guest RAM. Now, those VMs have 3.8T
of RAM available, but I don't believe we've observed a situation where
they would have benefited from having 2.5 gigs of buffers posted for
incoming network traffic :)

The second reason is interrupt related -- as I mentioned above, we
have found no workloads that clearly benefit from so many queues, but
we have found workloads that degrade. In particular workloads that do
a lot of small packet processing but which aren't extremely latency
sensitive can achieve higher PPS by taking fewer interrupt across
fewer VCPUs due to better batching (this also incurs higher latency,
but at the limit the "busy" cores end up suppressing most interrupts
and spending most of their cycles farming out work). Memcache is a
good example here, particularly if the latency targets for request
completion are in the ~milliseconds range (rather than the
microseconds we typically strive for with TCP_RR-style workloads).

All of that said, we haven't been forthcoming with data (and
unfortunately I don't have it handy in a useful form, otherwise I'd
simply post it here), so I understand the hesitation to simply run
with napi_tx across the board. As Willem said, this patch seemed like
the least disruptive way to allow us to continue down the road of
"universal" NAPI Tx and to hopefully get data across enough workloads
(with VMs small, large, and absurdly large :) to present a compelling
argument in one direction or another. As far as I know there aren't
currently any NAPI related ethtool commands (based on a quick perusal
of ethtool.h) -- it seems like it would be fairly involved/heavyweight
to plumb one solely for this unless NAPI Tx is something many users
will want to tune (and for which other drivers would support tuning).

^ permalink raw reply

* Re: [PATCH 1/4] treewide: convert ISO_8859-1 text comments to utf-8
From: Joe Perches @ 2018-07-25  0:13 UTC (permalink / raw)
  To: Andrew Morton, Arnd Bergmann
  Cc: Samuel Ortiz, David S. Miller, Rob Herring, Michael Ellerman,
	Jonathan Cameron, linux-wireless, netdev, devicetree,
	linux-kernel, linux-arm-kernel, linux-crypto, linuxppc-dev,
	linux-iio, linux-pm, lvs-devel, netfilter-devel, coreteam
In-Reply-To: <20180724140010.e24a9964fd340afe2d98a994@linux-foundation.org>

On Tue, 2018-07-24 at 14:00 -0700, Andrew Morton wrote:
> On Tue, 24 Jul 2018 13:13:25 +0200 Arnd Bergmann <arnd@arndb.de> wrote:
> > Almost all files in the kernel are either plain text or UTF-8
> > encoded. A couple however are ISO_8859-1, usually just a few
> > characters in a C comments, for historic reasons.
> > This converts them all to UTF-8 for consistency.
[]
> Will we be getting a checkpatch rule to keep things this way?

How would that be done?

^ permalink raw reply

* Re: [PATCH net-next] virtio_net: force_napi_tx module param.
From: Willem de Bruijn @ 2018-07-25  0:02 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: caleb.raitto, Jason Wang, David Miller, Network Development,
	Caleb Raitto
In-Reply-To: <20180725014410-mutt-send-email-mst@kernel.org>

On Tue, Jul 24, 2018 at 6:46 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Tue, Jul 24, 2018 at 06:31:54PM -0400, Willem de Bruijn wrote:
> > On Tue, Jul 24, 2018 at 6:23 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > >
> > > On Tue, Jul 24, 2018 at 04:52:53PM -0400, Willem de Bruijn wrote:
> > > > >From the above linked patch, I understand that there are yet
> > > > other special cases in production, such as a hard cap on #tx queues to
> > > > 32 regardless of number of vcpus.
> > >
> > > I don't think upstream kernels have this limit - we can
> > > now use vmalloc for higher number of queues.
> >
> > Yes. that patch* mentioned it as a google compute engine imposed
> > limit. It is exactly such cloud provider imposed rules that I'm
> > concerned about working around in upstream drivers.
> >
> > * for reference, I mean https://patchwork.ozlabs.org/patch/725249/
>
> Yea. Why does GCE do it btw?

I have no idea, either. I guess some host-side constraint.

^ permalink raw reply

* Re: [PATCH net v2] ip: in cmsg IP(V6)_ORIGDSTADDR call pskb_may_pull
From: David Miller @ 2018-07-24 23:36 UTC (permalink / raw)
  To: willemdebruijn.kernel; +Cc: netdev, eric.dumazet, willemb
In-Reply-To: <20180723233648.95739-1-willemdebruijn.kernel@gmail.com>

From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: Mon, 23 Jul 2018 19:36:48 -0400

> From: Willem de Bruijn <willemb@google.com>
> 
> Syzbot reported a read beyond the end of the skb head when returning
> IPV6_ORIGDSTADDR:
 ...
> This logic and its ipv4 counterpart read the destination port from
> the packet at skb_transport_offset(skb) + 4.
> 
> With MSG_MORE and a local SOCK_RAW sender, syzbot was able to cook a
> packet that stores headers exactly up to skb_transport_offset(skb) in
> the head and the remainder in a frag.
> 
> Call pskb_may_pull before accessing the pointer to ensure that it lies
> in skb head.
> 
> Link: http://lkml.kernel.org/r/CAF=yD-LEJwZj5a1-bAAj2Oy_hKmGygV6rsJ_WOrAYnv-fnayiQ@mail.gmail.com
> Reported-by: syzbot+9adb4b567003cac781f0@syzkaller.appspotmail.com
> Signed-off-by: Willem de Bruijn <willemb@google.com>

Applied and queued up for -stable, thanks!

^ permalink raw reply

* Re: [PATCH] Make Surface Dock 3 work again
From: David Miller @ 2018-07-24 23:34 UTC (permalink / raw)
  To: m.radtke; +Cc: oliver, hayeswang, netdev
In-Reply-To: <873212f4-8e8d-df81-683e-03f3b75659d2@uib.de>

From: Mathias Radtke <m.radtke@uib.de>
Date: Tue, 24 Jul 2018 12:08:45 +0200

> since Kernel 4.10 the usage of the Surface Dock 3 is broken.
> The network driver r8152 reports Tx Error -71.
> The patch removes the dock from the r8152 driver and also removed it
> from the cdc_ether drivers blacklist. Therefore the cdc_driver takes
> over and the dock works again.

Your email client severely corrupted this patch, please fix this and
send a test patch to yourself so you can make sure it applies cleanly
before sending the patch here again.

Also, please provide a proper Signed-off-by: tag in your commit
message.

Thank you.

^ permalink raw reply

* Re: [PATCH net 1/1] bnx2x: Fix invalid memory access in rss hash config path.
From: David Miller @ 2018-07-24 23:33 UTC (permalink / raw)
  To: sudarsana.kalluru; +Cc: netdev, ariel.elior
In-Reply-To: <20180724094352.5807-1-sudarsana.kalluru@cavium.com>

From: Sudarsana Reddy Kalluru <sudarsana.kalluru@cavium.com>
Date: Tue, 24 Jul 2018 02:43:52 -0700

> Rx hash/filter table configuration uses rss_conf_obj to configure filters
> in the hardware. This object is initialized only when the interface is
> brought up.
> This patch adds driver changes to configure rss params only when the device
> is in opened state. In port disabled case, the config will be cached in the
> driver structure which will be applied in the successive load path.
> 
> Please consider applying it to 'net' branch.
> 
> Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>

Applied, thank you.

^ permalink raw reply

* Re: [PATCH net] net/mlx4_core: Save the qpn from the input modifier in RST2INIT wrapper
From: David Miller @ 2018-07-24 23:31 UTC (permalink / raw)
  To: tariqt; +Cc: netdev, eranbe, jackm
In-Reply-To: <1532431675-13208-1-git-send-email-tariqt@mellanox.com>

From: Tariq Toukan <tariqt@mellanox.com>
Date: Tue, 24 Jul 2018 14:27:55 +0300

> From: Jack Morgenstein <jackm@dev.mellanox.co.il>
> 
> Function mlx4_RST2INIT_QP_wrapper saved the qp number passed in the qp
> context, rather than the one passed in the input modifier.
> 
> However, the qp number in the qp context is not defined as a
> required parameter by the FW. Therefore, drivers may choose to not
> specify the qp number in the qp context for the reset-to-init transition.
> 
> Thus, we must save the qp number passed in the command input modifier --
> which is always present. (This saved qp number is used as the input
> modifier for command 2RST_QP when a slave's qp's are destroyed).
> 
> Fixes: c82e9aa0a8bc ("mlx4_core: resource tracking for HCA resources used by guests")
> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
> Signed-off-by: Tariq Toukan <tariqt@mellanox.com>

Applied and queued up for -stable, thank you.

^ permalink raw reply

* Re: [RFC iproute2-next v1 5/5] tc: Add support for configuring the taprio scheduler
From: Vinicius Costa Gomes @ 2018-07-24 23:20 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev, jhs, xiyou.wangcong, jiri, jesus.sanchez-palencia
In-Reply-To: <87sh4h3j8t.fsf@intel.com>

Hi,

Vinicius Costa Gomes <vinicius.gomes@intel.com> writes:

> Hi,
>
> Stephen Hemminger <stephen@networkplumber.org> writes:
>

[...]

>>
>> Why not just use batch mode? Introducing another input mode in tc that is
>> only in one qdisc seems like a bad idea.
>
> Seems that I have missed batch mode. I am going to play with it a little
> and see how things would look.
>

I finally had the chance to play with this, and indeed batch mode is
quite nice. Will replace the custom file input mode on the next
iteration. Thanks.


Cheers,

^ permalink raw reply

* Re: [patch net-next v4 03/12] net: sched: introduce chain object to uapi
From: Cong Wang @ 2018-07-24 23:20 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Linux Kernel Network Developers, David Miller, Jamal Hadi Salim,
	Jakub Kicinski, Simon Horman, john.hurley, David Ahern, mlxsw,
	sridhar.samudrala
In-Reply-To: <CAM_iQpU41g_aSd7wbRk5r+hbVRdoDYnLWANjOJtZYgf4qfx0_w@mail.gmail.com>

On Tue, Jul 24, 2018 at 3:30 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> On Mon, Jul 23, 2018 at 12:25 AM Jiri Pirko <jiri@resnulli.us> wrote:
> > +       switch (n->nlmsg_type) {
> > +       case RTM_NEWCHAIN:
> > +               /* In case the chain was successfully added, take a reference
> > +                * to the chain. This ensures that an empty chain
> > +                * does not disappear at the end of this function.
> > +                */
> > +               tcf_chain_hold(chain);
> > +               chain->explicitly_created = true;
> > +               tc_chain_notify(chain, NULL, 0, NLM_F_CREATE | NLM_F_EXCL,
> > +                               RTM_NEWCHAIN, false);
> > +               break;
> > +       case RTM_DELCHAIN:
> > +               /* Flush the chain first as the user requested chain removal. */
> > +               tcf_chain_flush(chain);
> > +               /* In case the chain was successfully deleted, put a reference
> > +                * to the chain previously taken during addition.
> > +                */
> > +               tcf_chain_put_explicitly_created(chain);
> > +               break;
>
> I don't see you send notification to user-space when deleting a chain,
> am I missing anything?

Oh, it is hidden in tcf_chain_put():

void tcf_chain_put(struct tcf_chain *chain)
{
        if (--chain->refcnt == 0) {
                tc_chain_notify(chain, NULL, 0, 0, RTM_DELCHAIN, false);
                tc_chain_tmplt_del(chain);
                tcf_chain_destroy(chain);
        }
}

So, you only send out notification when the last refcnt is gone.

If the chain that is being deleted by a user is still used by an action,
you return 0 or -EPERM?

^ permalink raw reply

* Re: selftests/bpf test_sockmap failure
From: Yonghong Song @ 2018-07-24 23:02 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Martin Lau
In-Reply-To: <6c0bebae-e3b4-8a69-0b51-df7de9414d64@gmail.com>



On 7/24/18 3:40 PM, John Fastabend wrote:
> On 07/24/2018 08:45 AM, Yonghong Song wrote:
>> In one of our production machines, tools/testing/selftests/bpf
>> test_sockmap failed randomly like below:
>>
>> ...
>> [TEST 78]: (512, 1, 1, sendmsg, pass,apply 1,): rx thread exited with
>> err 1. FAILED
>> ...
>>
>> ...
>> [TEST 80]: (2, 1024, 256, sendmsg, pass,apply 1,): rx thread exited with
>> err 1. FAILED
>> ...
>>
>> ...
>> [TEST 83]: (100, 1, 5, sendpage, pass,apply 1,): rx thread exited with
>> err 1. FAILED
>> ...
>>
>> ...
>> [TEST 79]: (512, 1, 1, sendpage, pass,apply 1,): rx thread exited with
>> err 1. FAILED
>> ...
>>
>> The command line is just `test_sockmap`. The machine has 80 cpus, 256G
>> memory. The kernel is based on 4.16 but backported with latest bpf-next
>> bpf changes.
>>
>> The failed test number (78, 79, 80, or 83) is random. But they all share
>> similar characteristics:
>>     . the option rate is greater than one, i.e., more than one
>>       sendmsg/sendpage in the sender forked process.
>>     . The txmsg_apply is not 0
>>
>> I debugged a little bit. It happens in msg_loop() function below
>> "unexpected timeout" path.
>>
>> ...
>>                          slct = select(max_fd + 1, &w, NULL, NULL,
>> &timeout);
>>                          if (slct == -1) {
>>                                  perror("select()");
>>                                  clock_gettime(CLOCK_MONOTONIC, &s->end);
>>                                  goto out_errno;
>>                          } else if (!slct) {
>>                                  if (opt->verbose)
>>                                          fprintf(stderr, "unexpected
>> timeout\n");
>>                                  errno = -EIO;
>>                                  clock_gettime(CLOCK_MONOTONIC, &s->end);
>>                                  goto out_errno;
>>                          }
>> ...
>>
>> It appears that when the error happens, the receive process does not
>> receive all bytes sent from the send process and eventually times out.
>>
>> Has anybody seen this issue as well?
>> John, any comments on this failure?
> 
> Can you run the test with verbose enabled so we can determine if the tx
> side is even sending the message? Sample patch below. This will allow
> us to see the tx bytes and rx bytes, although it will be a bit noisy.
> 
> I notice that the test program is not smart enough to (re)send bytes if
> the sendmsg call doesn't consume all bytes. This is a valid error if
> we get a enomem or other normal error on the tx side. With apply this
> is more likely because every byte (in apply = 1 case) is being sent
> through BPF prog.

The following are some of logs for the failed tests:

...
[TEST 78]: (512, 1, 1, sendmsg, pass,apply 1,): connected sockets: c1 
<-> p1, c2 <-> p2
cgroups binding: c1(24) <-> s1(22) - - - c2(25) <-> s2(23)
tx_sendmsg: TX: 512B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
0.000000GB/s
unexpected timeout
msg_loop_rx: iov_count 1 iov_buf 1 cnt 512 err -5
rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 147B 147.000000B/s 
0.000000GB/s
rx thread exited with err 1. FAILED
...

[TEST 82]: (100, 1, 5, sendmsg, pass,apply 1,): connected sockets: c1 
<-> p1, c2 <-> p2
cgroups binding: c1(24) <-> s1(22) - - - c2(25) <-> s2(23)
tx_sendmsg: TX: 500B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
0.000000GB/s
unexpected timeout
msg_loop_rx: iov_count 1 iov_buf 5 cnt 100 err -5
rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 366B 366.000000B/s 
0.000000GB/s
rx thread exited with err 1. FAILED

[TEST 402]: (512, 1, 1, sendmsg, pass,apply 1,): connected sockets: c1 
<-> p1, c2 <-> p2
cgroups binding: c1(42) <-> s1(40) - - - c2(43) <-> s2(41)
tx_sendmsg: TX: 512B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
0.000000GB/s
unexpected timeout
msg_loop_rx: iov_count 1 iov_buf 1 cnt 512 err -5
rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 147B 147.000000B/s 
0.000000GB/s
rx thread exited with err 1. FAILED

[TEST 80]: (2, 1024, 256, sendmsg, pass,apply 1,): connected sockets: c1 
<-> p1, c2 <-> p2
cgroups binding: c1(24) <-> s1(22) - - - c2(25) <-> s2(23)
tx_sendmsg: TX: 524288B 0.000000B/s 0.000000 GB/s RX: 0B 0.000000B/s 
0.000000GB/s
unexpected timeout
msg_loop_rx: iov_count 1024 iov_buf 256 cnt 2 err -5
rx_sendmsg: TX: 0B 0.000000B/s 0.000000GB/s RX: 458805B 458805.000000B/s 
0.000459GB/s
rx thread exited with err 1. FAILED


> 
> If this is not the case I can do some more digging but I've not seen
> this before.

I cannot reproduce it in my FC27 VM (with latest bpf-next) either.
The bug only shows up on our production service which is a lot busier 
and has more cpus/memorys and some sysctl configurations are different 
from my VM setup.

> 
> Thanks!
> John
> 
> --- a/tools/testing/selftests/bpf/test_sockmap.c
> +++ b/tools/testing/selftests/bpf/test_sockmap.c
> @@ -1031,6 +1031,7 @@ static int test_exec(int cgrp, struct
> sockmap_options *opt)
>          if (err)
>                  goto out;
> 
> +       opt->verbose = true;
>          err = __test_exec(cgrp, SENDPAGE, opt);
>   out:
>          return err;
> 
> 
>>
>> Thanks,
>>
>> Yonghong
> 

^ permalink raw reply

* [PATCH net-next] Implement a rtnetlink device which simulates wifi.
From: Cody Schuffelen @ 2018-07-25  0:10 UTC (permalink / raw)
  To: Kalle Valo, David S. Miller, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, kernel-team-z5hGa2qSFaRBDgjK7y7TUQ

The device added here is used through "ip link add ... type virt_wifi"
The intention is to take over an existing network device and produce a
new one that appears like a wireless connection, returning enough canned
responses to nl80211 to satisfy a standard network manager. If
necessary, it can also be set up one step removed from an existing
network device, such as through a vlan/80211Q or macvlan connection to
not disrupt the existing network interface.

This is being used for Google's Remote Android Virtual Device project,
which runs Android devices in virtual machines. The standard network
interfaces provided inside the virtual machines are all ethernet.
However, Android is not interested in ethernet devices and would rather
connect to a wireless interface. This patch allows the virtual machine
guest to treat one of its network connections as wireless rather than
ethernet, satisfying Android's network connection requirements.

We believe this is a generally useful driver for simulating wireless
network connections in other environments where a wireless connection is
desired by some userspace process but is not available. Future work can
also include exporting the wireless control plane to userspace, so the
device can configure the behavior of the simulated wireless network
itself.

This is distinct from other testing efforts such as mac80211_hwsim by
being a cfg80211 device instead of mac80211 device, allowing straight
pass-through on the data plane instead of forcing packaging of ethernet
data into mac80211 frames.

Signed-off-by: A. Cody Schuffelen <schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Acked-by: Alistair Strachan <astrachan-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Acked-by: Greg Hartman <ghartman-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
Resending this patch, because the To: line was missing in the original
email.

 drivers/net/wireless/Kconfig     |   7 +
 drivers/net/wireless/Makefile    |   2 +
 drivers/net/wireless/virt_wifi.c | 544 +++++++++++++++++++++++++++++++
 3 files changed, 553 insertions(+)
 create mode 100644 drivers/net/wireless/virt_wifi.c

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 166920ae23f8..1781d8a7f05a 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -114,4 +114,11 @@ config USB_NET_RNDIS_WLAN
 
 	  If you choose to build a module, it'll be called rndis_wlan.
 
+config VIRT_WIFI
+	tristate "Wifi wrapper for ethernet drivers"
+	default n
+	---help---
+	  This option adds support for ethernet connections to appear as if they
+	  are wifi connections through a special rtnetlink device.
+
 endif # WLAN
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 7fc96306712a..6cfe74515c95 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -27,3 +27,5 @@ obj-$(CONFIG_PCMCIA_WL3501)	+= wl3501_cs.o
 obj-$(CONFIG_USB_NET_RNDIS_WLAN)	+= rndis_wlan.o
 
 obj-$(CONFIG_MAC80211_HWSIM)	+= mac80211_hwsim.o
+
+obj-$(CONFIG_VIRT_WIFI)	+= virt_wifi.o
diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c
new file mode 100644
index 000000000000..602bf462b444
--- /dev/null
+++ b/drivers/net/wireless/virt_wifi.c
@@ -0,0 +1,544 @@
+// SPDX-License-Identifier: GPL-2.0
+/* drivers/net/wireless/virt_wifi.c
+ *
+ * A fake implementation of cfg80211_ops that can be tacked on to an ethernet
+ * net_device to make it appear as a wireless connection.
+ *
+ * Copyright (C) 2018 Google, Inc.
+ *
+ * Author: schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org
+ */
+
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+
+struct virt_wifi_priv {
+	bool being_deleted;
+	struct cfg80211_scan_request *scan_request;
+	struct delayed_work scan_result;
+	struct delayed_work scan_complete;
+};
+
+static struct ieee80211_channel channel = {
+	.band = NL80211_BAND_5GHZ,
+	.center_freq = 5500,
+	.hw_value = 5500,
+
+	.flags = 0, /* ieee80211_channel_flags */
+	.max_antenna_gain = 20,
+	.max_power = 5500,
+	.max_reg_power = 9999,
+};
+
+static struct ieee80211_rate bitrate = {
+	.flags = IEEE80211_RATE_SHORT_PREAMBLE, /* ieee80211_rate_flags */
+	.bitrate = 1000,
+};
+
+static struct ieee80211_supported_band band_5ghz = {
+	.channels = &channel,
+	.bitrates = &bitrate,
+	.band = NL80211_BAND_5GHZ,
+	.n_channels = 1,
+	.n_bitrates = 1,
+};
+
+static struct cfg80211_inform_bss mock_inform_bss = {
+	/* ieee80211_channel* */ .chan = &channel,
+	/* nl80211_bss_scan_width */ .scan_width = NL80211_BSS_CHAN_WIDTH_20,
+	/* s32 */ .signal = 99,
+};
+
+static u8 fake_router_bssid[] = {4, 4, 4, 4, 4, 4};
+
+static int virt_wifi_scan(struct wiphy *wiphy,
+			  struct cfg80211_scan_request *request)
+{
+	struct virt_wifi_priv *priv = wiphy_priv(wiphy);
+
+	wiphy_debug(wiphy, "scan\n");
+
+	if (priv->scan_request || priv->being_deleted)
+		return -EBUSY;
+
+	if (request->ie_len > 0)
+		wiphy_debug(wiphy, "scan: first ie: %d\n", (int)request->ie[0]);
+
+	if (request->n_ssids > 0) {
+		int i;
+		u8 request_ssid_copy[IEEE80211_MAX_SSID_LEN + 1];
+
+		for (i = 0; i < request->n_ssids; i++) {
+			strncpy(request_ssid_copy, request->ssids[i].ssid,
+				request->ssids[i].ssid_len);
+			request_ssid_copy[request->ssids[i].ssid_len] = 0;
+			wiphy_debug(wiphy, "scan: ssid: %s\n",
+				    request_ssid_copy);
+		}
+	}
+
+	priv->scan_request = request;
+	schedule_delayed_work(&priv->scan_result, HZ / 100);
+
+	return 0;
+}
+
+static void virt_wifi_scan_result(struct work_struct *work)
+{
+	struct virt_wifi_priv *priv =
+		container_of(work, struct virt_wifi_priv,
+			     scan_result.work);
+	struct wiphy *wiphy = priv_to_wiphy(priv);
+	char ssid[] = "__VirtWifi";
+	struct cfg80211_bss *informed_bss;
+
+	mock_inform_bss.boottime_ns = ktime_get_boot_ns();
+
+	ssid[0] = WLAN_EID_SSID;
+	/* size of the array minus null terminator, length byte, tag byte */
+	ssid[1] = sizeof(ssid) - 3;
+
+	informed_bss =
+		cfg80211_inform_bss_data(wiphy, &mock_inform_bss,
+					 CFG80211_BSS_FTYPE_PRESP,
+					 fake_router_bssid,
+					 mock_inform_bss.boottime_ns,
+					 WLAN_CAPABILITY_ESS, 0, ssid,
+					 /* Truncate before the terminator. */
+					 sizeof(ssid) - 1, GFP_KERNEL);
+	cfg80211_put_bss(wiphy, informed_bss);
+
+	informed_bss =
+		cfg80211_inform_bss_data(wiphy, &mock_inform_bss,
+					 CFG80211_BSS_FTYPE_BEACON,
+					 fake_router_bssid,
+					 mock_inform_bss.boottime_ns,
+					 WLAN_CAPABILITY_ESS, 0, ssid,
+					 /* Truncate before the terminator. */
+					 sizeof(ssid) - 1, GFP_KERNEL);
+	cfg80211_put_bss(wiphy, informed_bss);
+
+	schedule_delayed_work(&priv->scan_complete, HZ / 100);
+}
+
+static void virt_wifi_scan_complete(struct work_struct *work)
+{
+	struct virt_wifi_priv *priv =
+		container_of(work, struct virt_wifi_priv,
+			     scan_complete.work);
+	struct cfg80211_scan_info scan_info = {
+		.aborted = false,
+	};
+
+	cfg80211_scan_done(priv->scan_request, &scan_info);
+	priv->scan_request = NULL;
+}
+
+static struct ieee80211_mgmt auth_mgmt_frame = {
+	.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT
+				     | IEEE80211_STYPE_AUTH),
+	.duration = cpu_to_le16(1), /* ??? */
+	.u = {
+		.auth = {
+			.auth_alg = WLAN_AUTH_OPEN,
+			/* auth request has 1, auth response has 2 */
+			.auth_transaction = cpu_to_le16(2),
+		},
+	},
+};
+
+static int virt_wifi_auth(struct wiphy *wiphy,  struct net_device *dev,
+			  struct cfg80211_auth_request *req)
+{
+	wiphy_debug(wiphy, "auth\n");
+	memcpy(auth_mgmt_frame.da, dev->dev_addr, dev->addr_len);
+	memcpy(auth_mgmt_frame.sa, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	memcpy(auth_mgmt_frame.bssid, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	/* Must call cfg80211_rx_mlme_mgmt to notify about the response to this.
+	 * This must hold the mutex for the wedev while calling the function.
+	 * Luckily the nl80211 code invoking this already holds that mutex.
+	 */
+	cfg80211_rx_mlme_mgmt(dev, (const u8 *)&auth_mgmt_frame,
+			      sizeof(auth_mgmt_frame));
+	return 0;
+}
+
+static struct ieee80211_mgmt assoc_mgmt_frame = {
+	.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT
+				     | IEEE80211_STYPE_ASSOC_RESP),
+	.duration = cpu_to_le16(1), /* ??? */
+	.u = {
+		.assoc_resp = {
+			.capab_info = cpu_to_le16(1),
+			.status_code = cpu_to_le16(0),
+			.aid = cpu_to_le16(2), /* "association id" */
+		},
+	},
+};
+
+static int virt_wifi_assoc(struct wiphy *wiphy, struct net_device *dev,
+			   struct cfg80211_assoc_request *req)
+{
+	wiphy_debug(wiphy, "assoc\n");
+	memcpy(assoc_mgmt_frame.da, dev->dev_addr, dev->addr_len);
+	memcpy(assoc_mgmt_frame.sa, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	memcpy(assoc_mgmt_frame.bssid, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	/* Must call cfg80211_rx_assoc_resp to notify about the response to
+	 * this. This must hold the mutex for the wedev while calling the
+	 * function. Luckily the nl80211 code invoking this already holds that
+	 * mutex.
+	 */
+	cfg80211_rx_assoc_resp(dev, req->bss, (const u8 *)&assoc_mgmt_frame,
+			       sizeof(assoc_mgmt_frame), -1);
+	return 0;
+}
+
+static struct ieee80211_mgmt deauth_mgmt_frame = {
+	.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT
+				     | IEEE80211_STYPE_DEAUTH),
+	.duration = cpu_to_le16(1), /* ??? */
+};
+
+static int virt_wifi_deauth(struct wiphy *wiphy, struct net_device *dev,
+			    struct cfg80211_deauth_request *req)
+{
+	wiphy_debug(wiphy, "deauth\n");
+	memcpy(deauth_mgmt_frame.da, dev->dev_addr, dev->addr_len);
+	memcpy(deauth_mgmt_frame.sa, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	memcpy(deauth_mgmt_frame.bssid, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	deauth_mgmt_frame.u.deauth.reason_code = cpu_to_le16(req->reason_code);
+	/* Must call cfg80211_rx_mlme_mgmt to notify about the response to this.
+	 * This must hold the mutex for the wedev while calling the function.
+	 * Luckily the nl80211 code invoking this already holds that mutex.
+	 */
+	cfg80211_rx_mlme_mgmt(dev, (const u8 *)&deauth_mgmt_frame,
+			      sizeof(auth_mgmt_frame));
+	return 0;
+}
+
+static struct ieee80211_mgmt disassoc_mgmt_frame = {
+	.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT
+				     | IEEE80211_STYPE_DISASSOC),
+	.duration = cpu_to_le16(1), /* ??? */
+};
+
+static int virt_wifi_disassoc(struct wiphy *wiphy, struct net_device *dev,
+			      struct cfg80211_disassoc_request *req)
+{
+	wiphy_debug(wiphy, "disassoc\n");
+	memcpy(disassoc_mgmt_frame.da, dev->dev_addr, dev->addr_len);
+	memcpy(disassoc_mgmt_frame.sa, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	memcpy(disassoc_mgmt_frame.bssid, fake_router_bssid,
+	       sizeof(fake_router_bssid));
+	disassoc_mgmt_frame.u.disassoc.reason_code =
+		cpu_to_le16(req->reason_code);
+	/* Must call cfg80211_rx_mlme_mgmt to notify about the response to this.
+	 * This must hold the mutex for the wedev while calling the function.
+	 * Luckily the nl80211 code invoking this already holds that mutex.
+	 */
+	cfg80211_rx_mlme_mgmt(dev, (const u8 *)&disassoc_mgmt_frame,
+			      sizeof(auth_mgmt_frame));
+	return 0;
+}
+
+static int virt_wifi_get_station(struct wiphy *wiphy, struct net_device *dev,
+				 const u8 *mac, struct station_info *sinfo)
+{
+	wiphy_debug(wiphy, "get_station\n");
+	/* Only the values used by netlink_utils.cpp. */
+	sinfo->filled = BIT(NL80211_STA_INFO_TX_PACKETS) |
+		BIT(NL80211_STA_INFO_TX_FAILED) | BIT(NL80211_STA_INFO_SIGNAL) |
+		BIT(NL80211_STA_INFO_TX_BITRATE);
+	sinfo->tx_packets = 1;
+	sinfo->tx_failed = 0;
+	sinfo->signal = -1; /* -1 is the maximum signal strength, somehow. */
+	sinfo->txrate = (struct rate_info) {
+		.legacy = 10000, /* units are 100kbit/s */
+	};
+	return 0;
+}
+
+static const struct cfg80211_ops virt_wifi_cfg80211_ops = {
+	.scan = virt_wifi_scan,
+
+	.auth = virt_wifi_auth,
+	.assoc = virt_wifi_assoc,
+	.deauth = virt_wifi_deauth,
+	.disassoc = virt_wifi_disassoc,
+
+	.get_station = virt_wifi_get_station,
+};
+
+static struct wireless_dev *virt_wireless_dev(struct device *device)
+{
+	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
+	struct virt_wifi_priv *priv;
+
+	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+
+	if (!wdev)
+		return ERR_PTR(-ENOMEM);
+
+	wdev->iftype = NL80211_IFTYPE_STATION;
+	wiphy = wiphy_new(&virt_wifi_cfg80211_ops,
+			  sizeof(struct virt_wifi_priv));
+
+	if (!wiphy) {
+		kfree(wdev);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	wdev->wiphy = wiphy;
+
+	/* 100 SSIDs should be enough for anyone! */
+	wiphy->max_scan_ssids = 101;
+	wiphy->max_scan_ie_len = 1000;
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+	wiphy->bands[NL80211_BAND_2GHZ] = NULL;
+	wiphy->bands[NL80211_BAND_5GHZ] = &band_5ghz;
+	wiphy->bands[NL80211_BAND_60GHZ] = NULL;
+
+	/* Don't worry about frequency regulations. */
+	wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				     BIT(NL80211_IFTYPE_AP) |
+				     BIT(NL80211_IFTYPE_P2P_CLIENT) |
+				     BIT(NL80211_IFTYPE_P2P_GO) |
+				     BIT(NL80211_IFTYPE_ADHOC) |
+				     BIT(NL80211_IFTYPE_MESH_POINT) |
+				     BIT(NL80211_IFTYPE_MONITOR);
+	wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
+			    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+			    WIPHY_FLAG_AP_UAPSD |
+			    WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
+			       NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
+			       NL80211_FEATURE_STATIC_SMPS |
+			       NL80211_FEATURE_DYNAMIC_SMPS |
+			       NL80211_FEATURE_AP_SCAN |
+			       NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+	set_wiphy_dev(wiphy, device);
+
+	priv = wiphy_priv(wiphy);
+	priv->being_deleted = false;
+	priv->scan_request = NULL;
+	INIT_DELAYED_WORK(&priv->scan_result, virt_wifi_scan_result);
+	INIT_DELAYED_WORK(&priv->scan_complete, virt_wifi_scan_complete);
+
+	return wdev;
+}
+
+struct virt_wifi_netdev_priv {
+	struct net_device *lowerdev;
+	struct net_device *upperdev;
+	struct work_struct register_wiphy_work;
+};
+
+static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb,
+					struct net_device *dev)
+{
+	struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+	skb->dev = priv->lowerdev;
+	return dev_queue_xmit(skb);
+}
+
+static const struct net_device_ops wifi_vlan_ops = {
+	.ndo_start_xmit = virt_wifi_start_xmit,
+};
+
+static void free_wiphy(struct net_device *dev)
+{
+	struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+	struct virt_wifi_priv *w_priv;
+
+	flush_work(&priv->register_wiphy_work);
+	if (dev->ieee80211_ptr && !IS_ERR(dev->ieee80211_ptr)) {
+		w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
+		w_priv->being_deleted = true;
+		flush_delayed_work(&w_priv->scan_result);
+		flush_delayed_work(&w_priv->scan_complete);
+
+		if (dev->ieee80211_ptr->wiphy->registered)
+			wiphy_unregister(dev->ieee80211_ptr->wiphy);
+		wiphy_free(dev->ieee80211_ptr->wiphy);
+		kfree(dev->ieee80211_ptr);
+	}
+}
+
+static void virt_wifi_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+	dev->netdev_ops = &wifi_vlan_ops;
+	dev->needs_free_netdev = true;
+	dev->priv_destructor = free_wiphy;
+}
+
+/* Called under rcu_read_lock() from netif_receive_skb */
+static rx_handler_result_t virt_wifi_rx_handler(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct virt_wifi_netdev_priv *priv =
+		rcu_dereference(skb->dev->rx_handler_data);
+
+	/* macvlan uses GFP_ATOMIC here. */
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb) {
+		dev_err(&priv->upperdev->dev, "can't skb_share_check\n");
+		return RX_HANDLER_CONSUMED;
+	}
+
+	*pskb = skb;
+	skb->dev = priv->upperdev;
+	skb->pkt_type = PACKET_HOST;
+	return RX_HANDLER_ANOTHER;
+}
+
+static void virt_wifi_register_wiphy(struct work_struct *work)
+{
+	struct virt_wifi_netdev_priv *priv =
+		container_of(work, struct virt_wifi_netdev_priv,
+			     register_wiphy_work);
+	struct wireless_dev *wdev = priv->upperdev->ieee80211_ptr;
+	int err;
+
+	err = wiphy_register(wdev->wiphy);
+	if (err < 0) {
+		dev_err(&priv->upperdev->dev, "can't wiphy_register (%d)\n",
+			err);
+
+		/* Roll back the net_device, it's not going to do wifi. */
+		rtnl_lock();
+		err = rtnl_delete_link(priv->upperdev);
+		rtnl_unlock();
+
+		/* rtnl_delete_link should only throw errors if it's not a
+		 * netlink device, but we know here it is already a virt_wifi
+		 * device.
+		 */
+		WARN_ONCE(err, "rtnl_delete_link failed on a virt_wifi device");
+	}
+}
+
+/* Called with rtnl lock held. */
+static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
+			     struct nlattr *tb[], struct nlattr *data[],
+			     struct netlink_ext_ack *extack)
+{
+	struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+	int err;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	priv->upperdev = dev;
+	priv->lowerdev = __dev_get_by_index(src_net,
+					    nla_get_u32(tb[IFLA_LINK]));
+
+	if (!priv->lowerdev)
+		return -ENODEV;
+	if (!tb[IFLA_MTU])
+		dev->mtu = priv->lowerdev->mtu;
+	else if (dev->mtu > priv->lowerdev->mtu)
+		return -EINVAL;
+
+	err = netdev_rx_handler_register(priv->lowerdev, virt_wifi_rx_handler,
+					 priv);
+	if (err != 0) {
+		dev_err(&priv->lowerdev->dev,
+			"can't netdev_rx_handler_register: %ld\n",
+			PTR_ERR(dev->ieee80211_ptr));
+		return err;
+	}
+
+	eth_hw_addr_inherit(dev, priv->lowerdev);
+	netif_stacked_transfer_operstate(priv->lowerdev, dev);
+
+	SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
+	dev->ieee80211_ptr = virt_wireless_dev(&priv->lowerdev->dev);
+
+	if (IS_ERR(dev->ieee80211_ptr)) {
+		dev_err(&priv->lowerdev->dev, "can't init wireless: %ld\n",
+			PTR_ERR(dev->ieee80211_ptr));
+		return PTR_ERR(dev->ieee80211_ptr);
+	}
+
+	err = register_netdevice(dev);
+	if (err) {
+		dev_err(&priv->lowerdev->dev, "can't register_netdevice: %d\n",
+			err);
+		goto remove_handler;
+	}
+
+	err = netdev_upper_dev_link(priv->lowerdev, dev, extack);
+	if (err) {
+		dev_err(&priv->lowerdev->dev, "can't netdev_upper_dev_link: %d\n",
+			err);
+		goto unregister_netdev;
+	}
+
+	/* The newlink callback is invoked while holding the rtnl lock, but
+	 * register_wiphy wants to claim the rtnl lock itself.
+	 */
+	INIT_WORK(&priv->register_wiphy_work, virt_wifi_register_wiphy);
+	schedule_work(&priv->register_wiphy_work);
+
+	return 0;
+remove_handler:
+	netdev_rx_handler_unregister(priv->lowerdev);
+unregister_netdev:
+	unregister_netdevice(dev);
+
+	return err;
+}
+
+/** Called with rtnl lock held. */
+static void virt_wifi_dellink(struct net_device *dev,
+			      struct list_head *head)
+{
+	struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+	netdev_rx_handler_unregister(priv->lowerdev);
+	netdev_upper_dev_unlink(priv->lowerdev, dev);
+
+	unregister_netdevice_queue(dev, head);
+
+	/* Deleting the wiphy is handled in the netdev destructor. */
+}
+
+static struct rtnl_link_ops virt_wifi_link_ops = {
+	.kind		= "virt_wifi",
+	.setup		= virt_wifi_setup,
+	.newlink	= virt_wifi_newlink,
+	.dellink	= virt_wifi_dellink,
+	.priv_size	= sizeof(struct virt_wifi_netdev_priv),
+};
+
+static int __init virt_wifi_init_module(void)
+{
+	return rtnl_link_register(&virt_wifi_link_ops);
+}
+
+static void __exit virt_wifi_cleanup_module(void)
+{
+	rtnl_link_unregister(&virt_wifi_link_ops);
+}
+
+module_init(virt_wifi_init_module);
+module_exit(virt_wifi_cleanup_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("A. Cody Schuffelen <schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>");
+MODULE_DESCRIPTION("Driver for a wireless wrapper of ethernet devices");
+MODULE_ALIAS_RTNL_LINK("virt_wifi");
-- 
2.18.0.233.g985f88cf7e-goog

^ 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