Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net] net/sched: cls_flower: Set egress_dev mark when calling into the HW driver
From: Jiri Pirko @ 2017-10-16 12:41 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: David S. Miller, Jiri Pirko, netdev, mlxsw, Roi Dayan
In-Reply-To: <1508145588-29959-1-git-send-email-ogerlitz@mellanox.com>

Mon, Oct 16, 2017 at 11:19:48AM CEST, ogerlitz@mellanox.com wrote:
>Commit 7091d8c '(net/sched: cls_flower: Add offload support using egress
>Hardware device') made sure (when fl_hw_replace_filter is called) to put
>the egress_dev mark on persisent structure instance. Hence, following calls
>into the HW driver for stats and deletion will note it and act accordingly.
>
>With commit de4784ca030f this property is lost and hence when called,
>the HW driver failes to operate (stats, delete) on the offloaded flow.
>
>Fix it by setting the egress_dev flag whenever the ingress device is
>different from the hw device since this is exactly the condition under
>which we're calling into the HW driver through the egress port net-device.
>
>Fixes: de4784ca030f ('net: sched: get rid of struct tc_to_netdev')
>Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
>Signed-off-by: Roi Dayan <roid@mellanox.com>

Acked-by: Jiri Pirko <jiri@mellanox.com>

^ permalink raw reply

* Re: [PATCH net-next] dsa: slave: support phy devices on external MII bus
From: Andrew Lunn @ 2017-10-16 12:40 UTC (permalink / raw)
  To: Martin Hundebøll
  Cc: David S . Miller, netdev, Vivien Didelot, Florian Fainelli
In-Reply-To: <20171016104525.26810-1-mnhu@prevas.dk>

>       /* internal MII */
>       mdio {
>         switch0phy1@1 {
>           reg = <1>;
>         };
>       };
> 
>       /* external MII */
>       mdio1 {
>         switch0phy0: switch0phy0@0 {
>           reg = <0>;
>         };

Hi Martin

You are missing a compatible string here. The binding document says:

- mdio?         : Container of PHYs and devices on the external MDIO
                          bus. The node must contains a compatible string of
                          "marvell,mv88e6xxx-mdio-external"

	  Andrew

^ permalink raw reply

* Re: [PATCH net-next] dsa: slave: support phy devices on external MII bus
From: Andrew Lunn @ 2017-10-16 12:32 UTC (permalink / raw)
  To: Martin Hundebøll
  Cc: David S . Miller, netdev, Vivien Didelot, Florian Fainelli
In-Reply-To: <20171016104525.26810-1-mnhu@prevas.dk>

On Mon, Oct 16, 2017 at 12:45:25PM +0200, Martin Hundebøll wrote:
> When configuring a switch port to use an external phy, the phy is
> connected to external switch MII bus:

Hi Martin

So this is a 6390?

So this used to work. I have a 10G phy connected to the external MII
bus on a 6390. I wonder when this got broken? Supporting phy-handle is
old code, so when i added the external MII i don't think i needed to
change any generic code.

I will take a closer look.

Thanks
  Andrew

^ permalink raw reply

* Re: [PATCH net 5/6] rtnetlink: check DO_SETLINK_NOTIFY correctly in do_setlink
From: Nicolas Dichtel @ 2017-10-16 12:20 UTC (permalink / raw)
  To: David Ahern, Xin Long, network dev; +Cc: davem, hannes
In-Reply-To: <f3e88287-e2b8-06a9-a139-7a528749ef9e@gmail.com>

Le 16/10/2017 à 03:17, David Ahern a écrit :
> [ cc'ed Nicolas ]
> 
> On 10/15/17 4:13 AM, Xin Long wrote:
>> The check 'status & DO_SETLINK_NOTIFY' in do_setlink doesn't really
>> work after status & DO_SETLINK_MODIFIED, as:
>>
>>   DO_SETLINK_MODIFIED 0x1
>>   DO_SETLINK_NOTIFY 0x3
>>
>> Considering that notifications are suppposed to be sent only when
>> status have the flag DO_SETLINK_NOTIFY, the right check would be:
>>
>>   (status & DO_SETLINK_NOTIFY) == DO_SETLINK_NOTIFY
>>
>> This would avoid lots of duplicated notifications when setting some
>> properties of a link.
>>
>> Fixes: ba9989069f4e ("rtnl/do_setlink(): notify when a netdev is modified")
>> Signed-off-by: Xin Long <lucien.xin@gmail.com>
Good catch, thank you.

Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>

^ permalink raw reply

* Re: usb/net/rt2x00: warning in rt2800_eeprom_word_index
From: Dmitry Vyukov @ 2017-10-16 12:19 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: Andrey Konovalov, Helmut Schaa, Kalle Valo, linux-wireless,
	netdev, LKML, Kostya Serebryany, syzkaller
In-Reply-To: <20171016094024.GD2553@redhat.com>

On Mon, Oct 16, 2017 at 11:40 AM, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> Hi Dmitry
>
> On Sat, Oct 14, 2017 at 04:38:03PM +0200, Dmitry Vyukov wrote:
>> On Thu, Oct 12, 2017 at 9:25 AM, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
>> > Hi
>> >
>> > On Mon, Oct 09, 2017 at 07:50:53PM +0200, Andrey Konovalov wrote:
>> >> I've got the following report while fuzzing the kernel with syzkaller.
>> >>
>> >> On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).
>> >>
>> >> I'm not sure whether this is a bug in the driver, or just a way to
>> >> report misbehaving device. In the latter case this shouldn't be a
>> >> WARN() call, since WARN() means bug in the kernel.
>> >
>> > This is about wrong EEPROM, which reported 3 tx streams on
>> > non 3 antenna device. I think WARN() is justified and thanks
>> > to the call trace I was actually able to to understand what
>> > happened.
>> >
>> > In general I do not think WARN() only means a kernel bug, it
>> > can be F/W or H/W bug too.
>>
>> Hi Stanislaw,
>>
>> Printing messages is fine. Printing stacks is fine. Just please make
>> them distinguishable from kernel bugs and don't kill the whole
>> possibility of automated Linux kernel testing. That's an important
>> capability.
>
> We do not distinguish between bugs and other problems when WARN() is
> used in (wireless) drivers, what I think is correct, taking comment from
> include/asm-generic/bug.h :
>
> /*
>  * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
>  * significant issues that need prompt attention if they should ever
>  * appear at runtime.  Use the versions with printk format strings
>  * to provide better diagnostics.
>  */
>
> Historically we have BUG() to mark the bugs, but usage if it is not
> recommended as it can kill the system, so for anything that can
> be recovered in runtime - WARN() is recommended.
>
> Perhaps we can introduce another helper like PROBLEM() for marking
> situations when something is wrong, but it is not a bug. However I'm
> not even sure at what extent it can be used, since for many cases
> if not the most, driver author can not tell apriori if the problem
> is a bug in the driver or HW/FW misbehaviour (or maybe particular
> issue can happen because of both).

I will write a separate email to LKML.

Thanks

^ permalink raw reply

* Re: usb/net/rt2x00: warning in rt2800_eeprom_word_index
From: Dmitry Vyukov @ 2017-10-16 12:16 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Stanislaw Gruszka, Andrey Konovalov, Helmut Schaa, linux-wireless,
	netdev, LKML, Kostya Serebryany, syzkaller
In-Reply-To: <8760bfo09s.fsf@kamboji.qca.qualcomm.com>

On Mon, Oct 16, 2017 at 12:27 PM, Kalle Valo <kvalo@codeaurora.org> wrote:
> Dmitry Vyukov <dvyukov@google.com> writes:
>
>> On Thu, Oct 12, 2017 at 9:25 AM, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
>>> Hi
>>>
>>> On Mon, Oct 09, 2017 at 07:50:53PM +0200, Andrey Konovalov wrote:
>>>> I've got the following report while fuzzing the kernel with syzkaller.
>>>>
>>>> On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).
>>>>
>>>> I'm not sure whether this is a bug in the driver, or just a way to
>>>> report misbehaving device. In the latter case this shouldn't be a
>>>> WARN() call, since WARN() means bug in the kernel.
>>>
>>> This is about wrong EEPROM, which reported 3 tx streams on
>>> non 3 antenna device. I think WARN() is justified and thanks
>>> to the call trace I was actually able to to understand what
>>> happened.
>>>
>>> In general I do not think WARN() only means a kernel bug, it
>>> can be F/W or H/W bug too.
>>
>> Hi Stanislaw,
>>
>> Printing messages is fine. Printing stacks is fine. Just please make
>> them distinguishable from kernel bugs and don't kill the whole
>> possibility of automated Linux kernel testing. That's an important
>> capability.
>
> Not really following you. Are you saying that using WARN() prevents
> automated Linux kernel testing?


Absence of a way to understand when there is something wrong with
kernel (something to notify kernel developers about) is the problem.

^ permalink raw reply

* Re: RFC: making cn_proc work in {pid,user} namespaces
From: Aleksa Sarai @ 2017-10-16 12:11 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Linux Containers,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, dev,
	cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org >> Aleksa Sarai,
	Evgeniy Polyakov, Christian Brauner
In-Reply-To: <87r2u4nign.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

>> At the moment, cn_proc is not usable by containers or container runtimes. In
>> addition, all connectors have an odd relationship with init_net (for example,
>> /proc/net/connectors only exists in init_net). There are two main use-cases that
>> would be perfect for cn_proc, which is the reason for me pushing this:
>>
>> First, when adding a process to an existing container, in certain modes runc
>> would like to know that process's exit code. But, when joining a PID namespace,
>> it is advisable[1] to always double-fork after doing the setns(2) to reparent
>> the joining process to the init of the container (this causes the SIGCHLD to be
>> received by the container init).  It would also be useful to be able to monitor
>> the exit code of the init process in a container without being its parent. At
>> the moment, cn_proc doesn't allow unprivileged users to use it (making it a
>> problem for user namespaces and "rootless containers"). In addition, it also
>> doesn't allow nested containers to use it, because it requires the process to be
>> in init_pid. As a result, runc cannot use cn_proc and relies on SIGCHLD (which
>> can only be used if we don't double-fork, or keep around a long-running process
>> which is something that runc also cannot do).
> 
> As far as I know there are no technical issues that require a
> daemonizing double fork when injecting a process into a pid namespaces.
> A fork is required because the pid is changing and that requires another
> process.

 From memory I believe there was some issue that we saw, but because we 
couldn't collect exit codes we didn't look into it much further. I will 
try to write up a sample program to explain what I think the issue is 
(it's related to who gets SIGCHLD inside the container in the "attach" 
case).

> Monitoring and acting on the monitored state without keeping around a
> single process to do the monitoring does not make sense to me.  So I am
> just going to ignore that.

/me just realised you can't use SIGCHLD with double-fork, because that 
implies the process isn't actually reparented to the container's init. I 
was referring to the "middle" process in a double-fork here, but that 
obviously doesn't make sense.

> So I don't think fixing cn_proc for this issue makes sense.
> 
>> Secondly, there are/were some init systems that rely on cn_proc to manage
>> service state. From a "it would be neat" perspective, I think it would be quite
>> nice if such init systems could be used inside containers. But that requires
>> cn_proc to be able to be used as an unprivileged user and in a pid namespace
>> other than init_pid.
> 
> Any pointers to these init systems?  In general I agree.  Given how much
> work it takes to go through a subsystem and ensure that it is safe for
> non-root users I am happy to see the work done, but I am not
> volunteering for the work when I have several I have as many tasks as I
> have on my plate right now.

I *believe* (though I can't quite read scheme code) that GNU Shepherd 
(used to be called dmd) is the most recent example that uses cn_proc. 
Upstart /used/ to use it before they switched to ptrace.

However, we've also seen some users that are trying to use programs that 
make use of cn_proc inside containers[1]. So I don't think this is a 
problem that's going to go away (not to mention that I'm fairly 
convinced that cn_proc might be the only sane way to currently get 
process exit events if you're not their parent).

>> The /proc/net/connectors thing is quite easily resolved (just make it the
>> connector driver perdev and make some small changes to make sure the interfaces
>> stay sane inside of a container's network namespace). I'm sure that we'll
>> probably have to make some changes to the registration API, so that a connector
>> can specify whether they want to be visible to non-init_net
>> namespaces.
>>
>> However, the cn_proc problem is a bit harder to resolve nicely and there are
>> quite a few interface questions that would need to be agreed upon. The basic
>> idea would be that a process can only get cn_proc events if it has
>> ptrace_may_access rights over said process (effectively a forced filter -- which
>> would ideally be done send-side but it looks like it might have to be done
>> receive-side). This should resolve possible concerns about an unprivileged
>> process being able to inspect (fairly granular) information about the host. And
>> obviously the pids, uids, and gids would all be translated according to the
>> receiving process's user namespaces (if it cannot be translated then the message
>> is not received). I guess that the translation would be done in the same way as
>> SCM_CREDENTIALS (and cgroup.procs files), which is that it's done on the receive
>> side not the send side.
> 
> Hmm.  We have several of these things such as bsd process accounting
> which appear to be working fine.
> 
> The basic logic winds up being:
> for_each_receiver:
>      compose_msg in receivers namespace
>      send_msg.
> 
> The tricky bit in my mind is dealing with receivers because of the
> connection with the network namespace.
> 
> SCM_CREDENTIALS is an unfortunate case, that really should not be
> followed as a model.  The major challenge there is not knowing
> the receiving socket, or the receiver.  If I had been smarter
> when I coded that originally I would have forced everything into
> the namespace of the opener of the receiving socket.   I may have to
> revisit that one again someday and see if there are improvements that
> can be made.

When you say "namespace of the opener of the receiving socket", does 
that mean that if a process moves the fd to a different set of 
namespaces that the mappings will still be in relation to the old 
namespace? Or am I misunderstanding?

>> My reason for sending this email rather than just writing the patch is to see
>> whether anyone has any solid NACKs against the use-case or whether there is some
>> fundamental issue that I'm not seeing. If nobody objects, I'll be happy to work
>> on this.
> 
> If you want a non-crazy (with respect to namespace involvement) model
> please look at kernel/acct.c:acc_process()

Will do, I guess you're referring to do_acc_process()?

> If there are use cases that people still care about that use the
> proc connector and want to run in a container it seems sensible to dig
> in and sort things out.  I think I have been hoping it is little enough
> used we won't have to mess with making it work in namespaces.

There are a few other container-related bugs in it that need to be 
resolved anyway (see the discussion in [1] -- it's clearly not a 
security issue per-se but it is a correctness one). I'll try to work 
through those in either case, but I imagine that the architecture 
reworks necessary to fix those issues will make making it work for 
unprivileged users quite trivial (excluding the part where we have to 
verify that there's no security issues opened by it).

[1]: https://github.com/moby/moby/issues/30176

-- 
Aleksa Sarai
Snr. Software Engineer (Containers)
SUSE Linux GmbH
https://www.cyphar.com/

^ permalink raw reply

* [PATCH net-next v2 2/2] net: add skb_memcpy_to[from]_msg() to optimize skb code
From: yuan linyu @ 2017-10-16 12:11 UTC (permalink / raw)
  To: netdev; +Cc: David S . Miller, yuan linyu

From: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>

add these two wrappers in skbuff.h which is better named
than previous and only used for skb.

Signed-off-by: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>
---
 drivers/isdn/mISDN/socket.c        |  2 +-
 drivers/staging/irda/net/af_irda.c |  2 +-
 include/linux/skbuff.h             | 10 ++++++++++
 net/appletalk/ddp.c                |  2 +-
 net/ax25/af_ax25.c                 |  2 +-
 net/bluetooth/hci_sock.c           |  4 ++--
 net/bluetooth/rfcomm/sock.c        |  2 +-
 net/bluetooth/sco.c                |  2 +-
 net/caif/caif_socket.c             |  6 +++---
 net/can/bcm.c                      |  4 ++--
 net/can/raw.c                      |  4 ++--
 net/dccp/proto.c                   |  2 +-
 net/decnet/af_decnet.c             |  4 ++--
 net/ieee802154/socket.c            |  4 ++--
 net/ipx/ipx_route.c                |  2 +-
 net/key/af_key.c                   |  2 +-
 net/l2tp/l2tp_ip.c                 |  2 +-
 net/l2tp/l2tp_ppp.c                |  2 +-
 net/llc/af_llc.c                   |  2 +-
 net/netlink/af_netlink.c           |  2 +-
 net/nfc/rawsock.c                  |  2 +-
 net/packet/af_packet.c             |  2 +-
 net/phonet/datagram.c              |  2 +-
 net/phonet/pep.c                   |  2 +-
 24 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index c5603d1..19ecf62 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -202,7 +202,7 @@ mISDN_sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	if (!skb)
 		goto done;
 
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (skb_memcpy_from_msg(skb, msg, len)) {
 		err = -EFAULT;
 		goto done;
 	}
diff --git a/drivers/staging/irda/net/af_irda.c b/drivers/staging/irda/net/af_irda.c
index 23fa7c8..159fc1a 100644
--- a/drivers/staging/irda/net/af_irda.c
+++ b/drivers/staging/irda/net/af_irda.c
@@ -1469,7 +1469,7 @@ static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg,
 		}
 
 		chunk = min_t(unsigned int, skb->len, size);
-		if (memcpy_to_msg(msg, skb->data, chunk)) {
+		if (skb_memcpy_to_msg(msg, skb, chunk)) {
 			skb_queue_head(&sk->sk_receive_queue, skb);
 			if (copied == 0)
 				copied = -EFAULT;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 90868d1..901fa60 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3294,6 +3294,16 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
 struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
 			     gfp_t gfp);
 
+static inline int skb_memcpy_from_msg(struct sk_buff *skb, struct msghdr *msg, int len)
+{
+	return memcpy_from_msg(skb_put(skb, len), msg, len);
+}
+
+static inline int skb_memcpy_to_msg(struct msghdr *msg, struct sk_buff *skb, int len)
+{
+	return memcpy_to_msg(msg, skb->data, len);
+}
+
 struct skb_checksum_ops {
 	__wsum (*update)(const void *mem, int len, __wsum wsum);
 	__wsum (*combine)(__wsum csum, __wsum csum2, int offset, int len);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 5d035c1..c7846c3 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1658,7 +1658,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 
 	SOCK_DEBUG(sk, "SK %p: Copy user data (%zd bytes).\n", sk, len);
 
-	err = memcpy_from_msg(skb_put(skb, len), msg, len);
+	err = skb_memcpy_from_msg(skb, msg, len);
 	if (err) {
 		kfree_skb(skb);
 		err = -EFAULT;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index f3f9d18..442763e 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1552,7 +1552,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	skb_reserve(skb, size - len);
 
 	/* User data follows immediately after the AX.25 data */
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (skb_memcpy_from_msg(skb, msg, len)) {
 		err = -EFAULT;
 		kfree_skb(skb);
 		goto out;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 65d734c..349c79a 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1601,7 +1601,7 @@ static int hci_logging_frame(struct sock *sk, struct msghdr *msg, int len)
 	if (!skb)
 		return err;
 
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (skb_memcpy_from_msg(skb, msg, len)) {
 		err = -EFAULT;
 		goto drop;
 	}
@@ -1726,7 +1726,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
 	if (!skb)
 		goto done;
 
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (skb_memcpy_from_msg(skb, msg, len)) {
 		err = -EFAULT;
 		goto drop;
 	}
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 1aaccf6..41d19dc 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -594,7 +594,7 @@ static int rfcomm_sock_sendmsg(struct socket *sock, struct msghdr *msg,
 		}
 		skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
 
-		err = memcpy_from_msg(skb_put(skb, size), msg, size);
+		err = skb_memcpy_from_msg(skb, msg, size);
 		if (err) {
 			kfree_skb(skb);
 			if (sent == 0)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 795e920..01958d2 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -288,7 +288,7 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
 	if (!skb)
 		return err;
 
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (skb_memcpy_from_msg(skb, msg, len)) {
 		kfree_skb(skb);
 		return -EFAULT;
 	}
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 632d5a4..6b49e5a 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -422,7 +422,7 @@ static int caif_stream_recvmsg(struct socket *sock, struct msghdr *msg,
 		}
 		release_sock(sk);
 		chunk = min_t(unsigned int, skb->len, size);
-		if (memcpy_to_msg(msg, skb->data, chunk)) {
+		if (skb_memcpy_to_msg(msg, skb, chunk)) {
 			skb_queue_head(&sk->sk_receive_queue, skb);
 			if (copied == 0)
 				copied = -EFAULT;
@@ -570,7 +570,7 @@ static int caif_seqpkt_sendmsg(struct socket *sock, struct msghdr *msg,
 
 	skb_reserve(skb, cf_sk->headroom);
 
-	ret = memcpy_from_msg(skb_put(skb, len), msg, len);
+	ret = skb_memcpy_from_msg(skb, msg, len);
 
 	if (ret)
 		goto err;
@@ -645,7 +645,7 @@ static int caif_stream_sendmsg(struct socket *sock, struct msghdr *msg,
 		 */
 		size = min_t(int, size, skb_tailroom(skb));
 
-		err = memcpy_from_msg(skb_put(skb, size), msg, size);
+		err = skb_memcpy_from_msg(skb, msg, size);
 		if (err) {
 			kfree_skb(skb);
 			goto out_err;
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 47a8748d..6fb4670 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1269,7 +1269,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk,
 
 	can_skb_reserve(skb);
 
-	err = memcpy_from_msg(skb_put(skb, cfsiz), msg, cfsiz);
+	err = skb_memcpy_from_msg(skb, msg, cfsiz);
 	if (err < 0) {
 		kfree_skb(skb);
 		return err;
@@ -1642,7 +1642,7 @@ static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
 	if (skb->len < size)
 		size = skb->len;
 
-	err = memcpy_to_msg(msg, skb->data, size);
+	err = skb_memcpy_to_msg(msg, skb, size);
 	if (err < 0) {
 		skb_free_datagram(sk, skb);
 		return err;
diff --git a/net/can/raw.c b/net/can/raw.c
index 864c80d..b52d1db 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -766,7 +766,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 	can_skb_prv(skb)->ifindex = dev->ifindex;
 	can_skb_prv(skb)->skbcnt = 0;
 
-	err = memcpy_from_msg(skb_put(skb, size), msg, size);
+	err = skb_memcpy_from_msg(skb, msg, size);
 	if (err < 0)
 		goto free_skb;
 
@@ -813,7 +813,7 @@ static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
 	else
 		size = skb->len;
 
-	err = memcpy_to_msg(msg, skb->data, size);
+	err = skb_memcpy_to_msg(msg, skb, size);
 	if (err < 0) {
 		skb_free_datagram(sk, skb);
 		return err;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index b68168f..affe21a 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -785,7 +785,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 		goto out_release;
 
 	skb_reserve(skb, sk->sk_prot->max_header);
-	rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+	rc = skb_memcpy_from_msg(skb, msg, len);
 	if (rc != 0)
 		goto out_discard;
 
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 73a0399..6fa54fd 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1765,7 +1765,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
 		if ((chunk + copied) > size)
 			chunk = size - copied;
 
-		if (memcpy_to_msg(msg, skb->data, chunk)) {
+		if (skb_memcpy_to_msg(msg, skb, chunk)) {
 			rv = -EFAULT;
 			break;
 		}
@@ -2036,7 +2036,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
 		skb_reserve(skb, 64 + DN_MAX_NSP_DATA_HEADER);
 
-		if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+		if (skb_memcpy_from_msg(skb, msg, len)) {
 			err = -EFAULT;
 			goto out;
 		}
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index a60658c..c4072a4 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c
@@ -296,7 +296,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 	skb_reset_mac_header(skb);
 	skb_reset_network_header(skb);
 
-	err = memcpy_from_msg(skb_put(skb, size), msg, size);
+	err = skb_memcpy_from_msg(skb, msg, size);
 	if (err < 0)
 		goto out_skb;
 
@@ -684,7 +684,7 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 	if (err < 0)
 		goto out_skb;
 
-	err = memcpy_from_msg(skb_put(skb, size), msg, size);
+	err = skb_memcpy_from_msg(skb, msg, size);
 	if (err < 0)
 		goto out_skb;
 
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index b5d9144..72c8403 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -229,7 +229,7 @@ int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
 	memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);
 	ipx->ipx_dest.sock		= usipx->sipx_port;
 
-	rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+	rc = skb_memcpy_from_msg(skb, msg, len);
 	if (rc) {
 		kfree_skb(skb);
 		goto out_put;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index a00d607..af9b4b9 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3637,7 +3637,7 @@ static int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 		goto out;
 
 	err = -EFAULT;
-	if (memcpy_from_msg(skb_put(skb,len), msg, len))
+	if (skb_memcpy_from_msg(skb, msg, len))
 		goto out;
 
 	hdr = pfkey_get_base_msg(skb, &err);
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 4d322c1..3640f92 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -458,7 +458,7 @@ static int l2tp_ip_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 	*((__be32 *) skb_put(skb, 4)) = 0;
 
 	/* Copy user data into skb */
-	rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+	rc = skb_memcpy_from_msg(skb, msg, len);
 	if (rc < 0) {
 		kfree_skb(skb);
 		goto error;
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index bc6e8bf..c54ebaf 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -329,7 +329,7 @@ static int pppol2tp_sendmsg(struct socket *sock, struct msghdr *m,
 	skb_put(skb, 2);
 
 	/* Copy user data into skb */
-	error = memcpy_from_msg(skb_put(skb, total_len), m, total_len);
+	error = skb_memcpy_from_msg(skb, m, total_len);
 	if (error < 0) {
 		kfree_skb(skb);
 		goto error_put_sess_tun;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index c38d16f..aed88a1 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -928,7 +928,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	skb->dev      = llc->dev;
 	skb->protocol = llc_proto_type(addr->sllc_arphrd);
 	skb_reserve(skb, hdrlen);
-	rc = memcpy_from_msg(skb_put(skb, copied), msg, copied);
+	rc = skb_memcpy_from_msg(skb, msg, copied);
 	if (rc)
 		goto out;
 	if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) {
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index f347506..5ce9ac2 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1844,7 +1844,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	NETLINK_CB(skb).flags	= netlink_skb_flags;
 
 	err = -EFAULT;
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (skb_memcpy_from_msg(skb, msg, len)) {
 		kfree_skb(skb);
 		goto out;
 	}
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index e2188de..a7bf4d4 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -230,7 +230,7 @@ static int rawsock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	if (skb == NULL)
 		return rc;
 
-	rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+	rc = skb_memcpy_from_msg(skb, msg, len);
 	if (rc < 0) {
 		kfree_skb(skb);
 		return rc;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 3f5caa3..162460b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1972,7 +1972,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
 			if (len < hhlen)
 				skb_reset_network_header(skb);
 		}
-		err = memcpy_from_msg(skb_put(skb, len), msg, len);
+		err = skb_memcpy_from_msg(skb, msg, len);
 		if (err)
 			goto out_free;
 		goto retry;
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
index b44fb90..1ea1105 100644
--- a/net/phonet/datagram.c
+++ b/net/phonet/datagram.c
@@ -108,7 +108,7 @@ static int pn_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 		return err;
 	skb_reserve(skb, MAX_PHONET_HEADER);
 
-	err = memcpy_from_msg((void *)skb_put(skb, len), msg, len);
+	err = skb_memcpy_from_msg(skb, msg, len);
 	if (err < 0) {
 		kfree_skb(skb);
 		return err;
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 9fc76b1..84870b6 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1143,7 +1143,7 @@ static int pep_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 		return err;
 
 	skb_reserve(skb, MAX_PHONET_HEADER + 3 + pn->aligned);
-	err = memcpy_from_msg(skb_put(skb, len), msg, len);
+	err = skb_memcpy_from_msg(skb, msg, len);
 	if (err < 0)
 		goto outfree;
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH net-next v2 1/2] net: move memcpy_to[from]_msg() from skbuff.h to socket.h
From: yuan linyu @ 2017-10-16 12:10 UTC (permalink / raw)
  To: netdev; +Cc: David S . Miller, yuan linyu

From: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>

these two functions used by skb and other places,
move to socket.h where struct msghdr defined.

Signed-off-by: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>
---
 include/linux/skbuff.h | 10 ----------
 include/linux/socket.h | 13 ++++++++++++-
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 03634ec2..90868d1 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3294,16 +3294,6 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
 struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
 			     gfp_t gfp);
 
-static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
-{
-	return copy_from_iter_full(data, len, &msg->msg_iter) ? 0 : -EFAULT;
-}
-
-static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len)
-{
-	return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT;
-}
-
 struct skb_checksum_ops {
 	__wsum (*update)(const void *mem, int len, __wsum wsum);
 	__wsum (*combine)(__wsum csum, __wsum csum2, int offset, int len);
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 8ad963c..0a2048e 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -2,6 +2,7 @@
 #define _LINUX_SOCKET_H
 
 
+#include <linux/errno.h>
 #include <asm/socket.h>			/* arch-dependent defines	*/
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
 #include <linux/uio.h>			/* iovec support		*/
@@ -53,7 +54,17 @@ struct msghdr {
 	unsigned int	msg_flags;	/* flags on received message */
 	struct kiocb	*msg_iocb;	/* ptr to iocb for async requests */
 };
- 
+
+static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
+{
+	return copy_from_iter_full(data, len, &msg->msg_iter) ? 0 : -EFAULT;
+}
+
+static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len)
+{
+	return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT;
+}
+
 struct user_msghdr {
 	void		__user *msg_name;	/* ptr to socket address structure */
 	int		msg_namelen;		/* size of socket address structure */
-- 
2.7.4

^ permalink raw reply related

* [PATCH net-next v2 0/2] net: add memcpy_to[from]_msg()
From: yuan linyu @ 2017-10-16 12:10 UTC (permalink / raw)
  To: netdev; +Cc: David S . Miller, yuan linyu

From: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>

v2:
  fix kbuild warning

yuan linyu (2):
  net: move memcpy_to[from]_msg() from skbuff.h to socket.h
  net: add skb_memcpy_to[from]_msg() to optimize skb code

 drivers/isdn/mISDN/socket.c        |  2 +-
 drivers/staging/irda/net/af_irda.c |  2 +-
 include/linux/skbuff.h             |  8 ++++----
 include/linux/socket.h             | 13 ++++++++++++-
 net/appletalk/ddp.c                |  2 +-
 net/ax25/af_ax25.c                 |  2 +-
 net/bluetooth/hci_sock.c           |  4 ++--
 net/bluetooth/rfcomm/sock.c        |  2 +-
 net/bluetooth/sco.c                |  2 +-
 net/caif/caif_socket.c             |  6 +++---
 net/can/bcm.c                      |  4 ++--
 net/can/raw.c                      |  4 ++--
 net/dccp/proto.c                   |  2 +-
 net/decnet/af_decnet.c             |  4 ++--
 net/ieee802154/socket.c            |  4 ++--
 net/ipx/ipx_route.c                |  2 +-
 net/key/af_key.c                   |  2 +-
 net/l2tp/l2tp_ip.c                 |  2 +-
 net/l2tp/l2tp_ppp.c                |  2 +-
 net/llc/af_llc.c                   |  2 +-
 net/netlink/af_netlink.c           |  2 +-
 net/nfc/rawsock.c                  |  2 +-
 net/packet/af_packet.c             |  2 +-
 net/phonet/datagram.c              |  2 +-
 net/phonet/pep.c                   |  2 +-
 25 files changed, 46 insertions(+), 35 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH net] dev_ioctl: add missing NETDEV_CHANGE_TX_QUEUE_LEN event notification
From: Xin Long @ 2017-10-16 11:43 UTC (permalink / raw)
  To: network dev; +Cc: davem

When changing dev tx_queue_len via netlink or net-sysfs,
a NETDEV_CHANGE_TX_QUEUE_LEN event notification will be
called.

But dev_ioctl missed this event notification, which could
cause no userspace notification would be sent.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/core/dev_ioctl.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 709a4e6..f9c7a88 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -303,7 +303,18 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
 	case SIOCSIFTXQLEN:
 		if (ifr->ifr_qlen < 0)
 			return -EINVAL;
-		dev->tx_queue_len = ifr->ifr_qlen;
+		if (dev->tx_queue_len ^ ifr->ifr_qlen) {
+			unsigned int orig_len = dev->tx_queue_len;
+
+			dev->tx_queue_len = ifr->ifr_qlen;
+			err = call_netdevice_notifiers(
+					NETDEV_CHANGE_TX_QUEUE_LEN, dev);
+			err = notifier_to_errno(err);
+			if (err) {
+				dev->tx_queue_len = orig_len;
+				return err;
+			}
+		}
 		return 0;
 
 	case SIOCSIFNAME:
-- 
2.1.0

^ permalink raw reply related

* [PATCH] [net-next] net: systemport: add NET_DSA dependency
From: Arnd Bergmann @ 2017-10-16 11:32 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Arnd Bergmann, David S. Miller, Michael Chan, Sathya Perla,
	Nicolas Pitre, netdev, linux-kernel

The notifier cause a link error when NET_DSA is a loadable
module:

drivers/net/ethernet/broadcom/bcmsysport.o: In function `bcm_sysport_remove':
bcmsysport.c:(.text+0x1582): undefined reference to `unregister_dsa_notifier'
drivers/net/ethernet/broadcom/bcmsysport.o: In function `bcm_sysport_probe':
bcmsysport.c:(.text+0x278d): undefined reference to `register_dsa_notifier'

This adds a dependency that forces the systemport driver to be
a loadable module as well when that happens, but otherwise
allows it to be built normally when DSA is either built-in or
completely disabled.

Fixes: d156576362c0 ("net: systemport: Establish lower/upper queue mapping")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/ethernet/broadcom/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 67134ece1107..af75156919ed 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -184,6 +184,7 @@ config BGMAC_PLATFORM
 config SYSTEMPORT
 	tristate "Broadcom SYSTEMPORT internal MAC support"
 	depends on OF
+	depends on NET_DSA || !NET_DSA
 	select MII
 	select PHYLIB
 	select FIXED_PHY
-- 
2.9.0

^ permalink raw reply related

* (unknown), 
From: kindergartenchaos2 @ 2017-10-16 11:30 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: 567333220.zip --]
[-- Type: application/zip, Size: 46094 bytes --]

^ permalink raw reply

* RE: [patch net 0/4] net/sched: Fix a system panic when deleting filters
From: Chris Mi @ 2017-10-16 11:20 UTC (permalink / raw)
  To: Jamal Hadi Salim, netdev@vger.kernel.org
  Cc: lucasb@mojatatu.com, xiyou.wangcong@gmail.com, jiri@resnulli.us,
	davem@davemloft.net
In-Reply-To: <556e3159-78ae-d07b-928e-37d99d380a3d@mojatatu.com>

Hi Jamal,

> -----Original Message-----
> From: Jamal Hadi Salim [mailto:jhs@mojatatu.com]
> Sent: Monday, October 16, 2017 7:06 PM
> To: Chris Mi <chrism@mellanox.com>; netdev@vger.kernel.org
> Cc: lucasb@mojatatu.com; xiyou.wangcong@gmail.com; jiri@resnulli.us;
> davem@davemloft.net
> Subject: Re: [patch net 0/4] net/sched: Fix a system panic when deleting
> filters
> 
> 
> Hi Chris,
> 
> On 17-10-16 04:31 AM, Chris Mi wrote:
> > If some filters share the same action, when deleting these filters,
> > system may panic. This patchset fixes this issue. And the test case
> > finding this issue is also integrated into tc test suite of selftests.
> >
> 
> I think this would read better if re-worded as:
> ---
> If some filters share the same action, when deleting these filters, it is
> possible to create a system panic. This is because deletions could be
> manipulated by many RCU callbacks at the same time.
> This patch set fixes these issues.
> To reproduce the issue run selftests in patch 3 and 4.
> To test if the issue was fixed, apply patches 1 and 2 and then repeat the tests.
> ------
Done.
> 
> Other than that all look good to me and:
> 
> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Done. And thanks for your review.

Thanks,
Chris
> 
> cheers,
> jamal

^ permalink raw reply

* Re: Linux 4.12+ memory leak on router with i40e NICs
From: Pavlos Parissis @ 2017-10-16 11:20 UTC (permalink / raw)
  To: Alexander Duyck, Paweł Staszewski
  Cc: Anders K. Pedersen | Cohaesio, netdev@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, alexander.h.duyck@intel.com
In-Reply-To: <CAKgT0UcOWxnrsGEjTopPP-JKyKGTG3j6KNKUbhQRgaCStyzr_A@mail.gmail.com>


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

On 15/10/2017 02:58 πμ, Alexander Duyck wrote:
> Hi Pawel,
> 
> To clarify is that Dave Miller's tree or Linus's that you are talking
> about? If it is Dave's tree how long ago was it you pulled it since I
> think the fix was just pushed by Jeff Kirsher a few days ago.
> 
> The issue should be fixed in the following commit:
> https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/drivers/net/ethernet/intel/i40e/i40e_txrx.c?id=2b9478ffc550f17c6cd8c69057234e91150f5972
> 


Do you know when it is going to be available on net-next and linux-stable repos?

Cheers,
Pavlos



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [patch net v2 4/4] selftests: Introduce a new test case to tc testsuite
From: Chris Mi @ 2017-10-16 11:18 UTC (permalink / raw)
  To: netdev; +Cc: jhs, lucasb, xiyou.wangcong, jiri, davem
In-Reply-To: <1508152718-28726-1-git-send-email-chrism@mellanox.com>

In this patchset, we fixed a tc bug. This patch adds the test case
that reproduces the bug. To run this test case, user should specify
an existing NIC device:
  # sudo ./tdc.py -d enp4s0f0

This test case belongs to category "flower". If user doesn't specify
a NIC device, the test cases belong to "flower" will not be run.

In this test case, we create 1M filters and all filters share the same
action. When destroying all filters, kernel should not panic. It takes
about 18s to run it.

Signed-off-by: Chris Mi <chrism@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 .../tc-testing/tc-tests/filters/tests.json         | 23 +++++++++++++++++++++-
 tools/testing/selftests/tc-testing/tdc.py          | 20 +++++++++++++++----
 tools/testing/selftests/tc-testing/tdc_config.py   |  2 ++
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
index c727b96..5fa02d8 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
@@ -17,5 +17,26 @@
         "teardown": [
             "$TC qdisc del dev $DEV1 ingress"
         ]
+    },
+    {
+        "id": "d052",
+        "name": "Add 1M filters with the same action",
+        "category": [
+            "filter",
+            "flower"
+        ],
+        "setup": [
+            "$TC qdisc add dev $DEV2 ingress",
+            "./tdc_batch.py $DEV2 $BATCH_FILE --share_action -n 1000000"
+        ],
+        "cmdUnderTest": "$TC -b $BATCH_FILE",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action gact",
+        "matchPattern": "action order 0: gact action drop.*index 1 ref 1000000 bind 1000000",
+        "matchCount": "1",
+        "teardown": [
+            "$TC qdisc del dev $DEV2 ingress",
+            "/bin/rm $BATCH_FILE"
+        ]
     }
-]
\ No newline at end of file
+]
diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py
index cd61b78..5f11f5d 100755
--- a/tools/testing/selftests/tc-testing/tdc.py
+++ b/tools/testing/selftests/tc-testing/tdc.py
@@ -88,7 +88,7 @@ def prepare_env(cmdlist):
             exit(1)
 
 
-def test_runner(filtered_tests):
+def test_runner(filtered_tests, args):
     """
     Driver function for the unit tests.
 
@@ -105,6 +105,8 @@ def test_runner(filtered_tests):
     for tidx in testlist:
         result = True
         tresult = ""
+        if "flower" in tidx["category"] and args.device == None:
+            continue
         print("Test " + tidx["id"] + ": " + tidx["name"])
         prepare_env(tidx["setup"])
         (p, procout) = exec_cmd(tidx["cmdUnderTest"])
@@ -152,6 +154,10 @@ def ns_create():
         exec_cmd(cmd, False)
         cmd = 'ip -s $NS link set $DEV1 up'
         exec_cmd(cmd, False)
+        cmd = 'ip link set $DEV2 netns $NS'
+        exec_cmd(cmd, False)
+        cmd = 'ip -s $NS link set $DEV2 up'
+        exec_cmd(cmd, False)
 
 
 def ns_destroy():
@@ -211,7 +217,8 @@ def set_args(parser):
                         help='Execute the single test case with specified ID')
     parser.add_argument('-i', '--id', action='store_true', dest='gen_id',
                         help='Generate ID numbers for new test cases')
-    return parser
+    parser.add_argument('-d', '--device',
+                        help='Execute the test case in flower category')
     return parser
 
 
@@ -225,6 +232,8 @@ def check_default_settings(args):
 
     if args.path != None:
          NAMES['TC'] = args.path
+    if args.device != None:
+         NAMES['DEV2'] = args.device
     if not os.path.isfile(NAMES['TC']):
         print("The specified tc path " + NAMES['TC'] + " does not exist.")
         exit(1)
@@ -381,14 +390,17 @@ def set_operation_mode(args):
             if (len(alltests) == 0):
                 print("Cannot find a test case with ID matching " + target_id)
                 exit(1)
-        catresults = test_runner(alltests)
+        catresults = test_runner(alltests, args)
         print("All test results: " + "\n\n" + catresults)
     elif (len(target_category) > 0):
+        if (target_category == "flower") and args.device == None:
+            print("Please specify a NIC device (-d) to run category flower")
+            exit(1)
         if (target_category not in ucat):
             print("Specified category is not present in this file.")
             exit(1)
         else:
-            catresults = test_runner(testcases[target_category])
+            catresults = test_runner(testcases[target_category], args)
             print("Category " + target_category + "\n\n" + catresults)
 
     ns_destroy()
diff --git a/tools/testing/selftests/tc-testing/tdc_config.py b/tools/testing/selftests/tc-testing/tdc_config.py
index 0108737..b635251 100644
--- a/tools/testing/selftests/tc-testing/tdc_config.py
+++ b/tools/testing/selftests/tc-testing/tdc_config.py
@@ -12,6 +12,8 @@ NAMES = {
           # Name of veth devices to be created for the namespace
           'DEV0': 'v0p0',
           'DEV1': 'v0p1',
+          'DEV2': '',
+          'BATCH_FILE': './batch.txt',
           # Name of the namespace to use
           'NS': 'tcut'
         }
-- 
1.8.3.1

^ permalink raw reply related

* [patch net v2 3/4] selftests: Introduce a new script to generate tc batch file
From: Chris Mi @ 2017-10-16 11:18 UTC (permalink / raw)
  To: netdev; +Cc: jhs, lucasb, xiyou.wangcong, jiri, davem
In-Reply-To: <1508152718-28726-1-git-send-email-chrism@mellanox.com>

  # ./tdc_batch.py -h
  usage: tdc_batch.py [-h] [-n NUMBER] [-o] [-s] [-p] device file

  TC batch file generator

  positional arguments:
    device                device name
    file                  batch file name

  optional arguments:
    -h, --help            show this help message and exit
    -n NUMBER, --number NUMBER
                          how many lines in batch file
    -o, --skip_sw         skip_sw (offload), by default skip_hw
    -s, --share_action    all filters share the same action
    -p, --prio            all filters have different prio

Signed-off-by: Chris Mi <chrism@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 tools/testing/selftests/tc-testing/tdc_batch.py | 62 +++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100755 tools/testing/selftests/tc-testing/tdc_batch.py

diff --git a/tools/testing/selftests/tc-testing/tdc_batch.py b/tools/testing/selftests/tc-testing/tdc_batch.py
new file mode 100755
index 0000000..707c6bf
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc_batch.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python3
+
+"""
+tdc_batch.py - a script to generate TC batch file
+
+Copyright (C) 2017 Chris Mi <chrism@mellanox.com>
+"""
+
+import argparse
+
+parser = argparse.ArgumentParser(description='TC batch file generator')
+parser.add_argument("device", help="device name")
+parser.add_argument("file", help="batch file name")
+parser.add_argument("-n", "--number", type=int,
+                    help="how many lines in batch file")
+parser.add_argument("-o", "--skip_sw",
+                    help="skip_sw (offload), by default skip_hw",
+                    action="store_true")
+parser.add_argument("-s", "--share_action",
+                    help="all filters share the same action",
+                    action="store_true")
+parser.add_argument("-p", "--prio",
+                    help="all filters have different prio",
+                    action="store_true")
+args = parser.parse_args()
+
+device = args.device
+file = open(args.file, 'w')
+
+number = 1
+if args.number:
+    number = args.number
+
+skip = "skip_hw"
+if args.skip_sw:
+    skip = "skip_sw"
+
+share_action = ""
+if args.share_action:
+    share_action = "index 1"
+
+prio = "prio 1"
+if args.prio:
+    prio = ""
+    if number > 0x4000:
+        number = 0x4000
+
+index = 0
+for i in range(0x100):
+    for j in range(0x100):
+        for k in range(0x100):
+            mac = ("%02x:%02x:%02x" % (i, j, k))
+            src_mac = "e4:11:00:" + mac
+            dst_mac = "e4:12:00:" + mac
+            cmd = ("filter add dev %s %s protocol ip parent ffff: flower %s "
+                   "src_mac %s dst_mac %s action drop %s" %
+                   (device, prio, skip, src_mac, dst_mac, share_action))
+            file.write("%s\n" % cmd)
+            index += 1
+            if index >= number:
+                file.close()
+                exit(0)
-- 
1.8.3.1

^ permalink raw reply related

* [patch net v2 1/4] net/sched: Change tc_action refcnt and bindcnt to atomic
From: Chris Mi @ 2017-10-16 11:18 UTC (permalink / raw)
  To: netdev; +Cc: jhs, lucasb, xiyou.wangcong, jiri, davem
In-Reply-To: <1508152718-28726-1-git-send-email-chrism@mellanox.com>

If many filters share the same action. That action's refcnt and bindcnt
could be manipulated by many RCU callbacks at the same time. This patch
makes these operations atomic.

Fixes commit in pre-git era.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Chris Mi <chrism@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 include/net/act_api.h      |  4 ++--
 net/sched/act_api.c        | 21 +++++++++++----------
 net/sched/act_bpf.c        |  4 ++--
 net/sched/act_connmark.c   |  4 ++--
 net/sched/act_csum.c       |  4 ++--
 net/sched/act_gact.c       |  4 ++--
 net/sched/act_ife.c        |  4 ++--
 net/sched/act_ipt.c        |  4 ++--
 net/sched/act_mirred.c     |  4 ++--
 net/sched/act_nat.c        |  4 ++--
 net/sched/act_pedit.c      |  4 ++--
 net/sched/act_police.c     |  4 ++--
 net/sched/act_sample.c     |  4 ++--
 net/sched/act_simple.c     |  4 ++--
 net/sched/act_skbedit.c    |  4 ++--
 net/sched/act_skbmod.c     |  4 ++--
 net/sched/act_tunnel_key.c |  4 ++--
 net/sched/act_vlan.c       |  4 ++--
 18 files changed, 45 insertions(+), 44 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index b944e0eb..a469ab6 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -25,8 +25,8 @@ struct tc_action {
 	struct tcf_idrinfo		*idrinfo;
 
 	u32				tcfa_index;
-	int				tcfa_refcnt;
-	int				tcfa_bindcnt;
+	atomic_t			tcfa_refcnt;
+	atomic_t			tcfa_bindcnt;
 	u32				tcfa_capab;
 	int				tcfa_action;
 	struct tcf_t			tcfa_tm;
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index da6fa82..9c0224d 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -88,12 +88,13 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
 
 	if (p) {
 		if (bind)
-			p->tcfa_bindcnt--;
-		else if (strict && p->tcfa_bindcnt > 0)
+			atomic_dec(&p->tcfa_bindcnt);
+		else if (strict && atomic_read(&p->tcfa_bindcnt) > 0)
 			return -EPERM;
 
-		p->tcfa_refcnt--;
-		if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
+		atomic_dec(&p->tcfa_refcnt);
+		if (atomic_read(&p->tcfa_bindcnt) == 0 &&
+		    atomic_read(&p->tcfa_refcnt) == 0) {
 			if (p->ops->cleanup)
 				p->ops->cleanup(p, bind);
 			tcf_idr_remove(p->idrinfo, p);
@@ -245,8 +246,8 @@ bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
 
 	if (index && p) {
 		if (bind)
-			p->tcfa_bindcnt++;
-		p->tcfa_refcnt++;
+			atomic_inc(&p->tcfa_bindcnt);
+		atomic_inc(&p->tcfa_refcnt);
 		*a = p;
 		return true;
 	}
@@ -274,9 +275,9 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
 
 	if (unlikely(!p))
 		return -ENOMEM;
-	p->tcfa_refcnt = 1;
+	atomic_set(&p->tcfa_refcnt, 1);
 	if (bind)
-		p->tcfa_bindcnt = 1;
+		atomic_set(&p->tcfa_bindcnt, 1);
 
 	if (cpustats) {
 		p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
@@ -727,7 +728,7 @@ static void cleanup_a(struct list_head *actions, int ovr)
 		return;
 
 	list_for_each_entry(a, actions, list)
-		a->tcfa_refcnt--;
+		atomic_dec(&a->tcfa_refcnt);
 }
 
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
@@ -751,7 +752,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
 		}
 		act->order = i;
 		if (ovr)
-			act->tcfa_refcnt++;
+			atomic_inc(&act->tcfa_refcnt);
 		list_add_tail(&act->list, actions);
 	}
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index c0c707e..4ddf281 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -141,8 +141,8 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
 	struct tcf_bpf *prog = to_bpf(act);
 	struct tc_act_bpf opt = {
 		.index   = prog->tcf_index,
-		.refcnt  = prog->tcf_refcnt - ref,
-		.bindcnt = prog->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&prog->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&prog->tcf_bindcnt) - bind,
 		.action  = prog->tcf_action,
 	};
 	struct tcf_t tm;
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 10b7a88..d2cf658 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -153,8 +153,8 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
 
 	struct tc_connmark opt = {
 		.index   = ci->tcf_index,
-		.refcnt  = ci->tcf_refcnt - ref,
-		.bindcnt = ci->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&ci->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
 		.action  = ci->tcf_action,
 		.zone   = ci->zone,
 	};
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 1c40caa..b9ca424 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -575,8 +575,8 @@ static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind,
 		.update_flags = p->update_flags,
 		.index   = p->tcf_index,
 		.action  = p->tcf_action,
-		.refcnt  = p->tcf_refcnt - ref,
-		.bindcnt = p->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&p->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&p->tcf_bindcnt) - bind,
 	};
 	struct tcf_t t;
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e29a48e..b1326b7 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -169,8 +169,8 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tcf_gact *gact = to_gact(a);
 	struct tc_gact opt = {
 		.index   = gact->tcf_index,
-		.refcnt  = gact->tcf_refcnt - ref,
-		.bindcnt = gact->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&gact->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&gact->tcf_bindcnt) - bind,
 		.action  = gact->tcf_action,
 	};
 	struct tcf_t t;
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 8ccd358..5cdcc87 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -551,8 +551,8 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
 	struct tcf_ife_info *ife = to_ife(a);
 	struct tc_ife opt = {
 		.index = ife->tcf_index,
-		.refcnt = ife->tcf_refcnt - ref,
-		.bindcnt = ife->tcf_bindcnt - bind,
+		.refcnt = atomic_read(&ife->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind,
 		.action = ife->tcf_action,
 		.flags = ife->flags,
 	};
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index d9e399a..02c14dc 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -277,8 +277,8 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
 	if (unlikely(!t))
 		goto nla_put_failure;
 
-	c.bindcnt = ipt->tcf_bindcnt - bind;
-	c.refcnt = ipt->tcf_refcnt - ref;
+	c.bindcnt = atomic_read(&ipt->tcf_bindcnt) - bind;
+	c.refcnt = atomic_read(&ipt->tcf_refcnt) - ref;
 	strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
 
 	if (nla_put(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t) ||
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 416627c..aeeeb38 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -249,8 +249,8 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind,
 	struct tc_mirred opt = {
 		.index   = m->tcf_index,
 		.action  = m->tcf_action,
-		.refcnt  = m->tcf_refcnt - ref,
-		.bindcnt = m->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&m->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&m->tcf_bindcnt) - bind,
 		.eaction = m->tcfm_eaction,
 		.ifindex = m->tcfm_ifindex,
 	};
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index c365d01..58fa1ae 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -256,8 +256,8 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
 
 		.index    = p->tcf_index,
 		.action   = p->tcf_action,
-		.refcnt   = p->tcf_refcnt - ref,
-		.bindcnt  = p->tcf_bindcnt - bind,
+		.refcnt   = atomic_read(&p->tcf_refcnt) - ref,
+		.bindcnt  = atomic_read(&p->tcf_bindcnt) - bind,
 	};
 	struct tcf_t t;
 
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 491fe5de..27b9fea 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -391,8 +391,8 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
 	opt->nkeys = p->tcfp_nkeys;
 	opt->flags = p->tcfp_flags;
 	opt->action = p->tcf_action;
-	opt->refcnt = p->tcf_refcnt - ref;
-	opt->bindcnt = p->tcf_bindcnt - bind;
+	opt->refcnt = atomic_read(&p->tcf_refcnt) - ref;
+	opt->bindcnt = atomic_read(&p->tcf_bindcnt) - bind;
 
 	if (p->tcfp_keys_ex) {
 		tcf_pedit_key_ex_dump(skb, p->tcfp_keys_ex, p->tcfp_nkeys);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 3bb2ebf..d8a1ac6 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -272,8 +272,8 @@ static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a,
 		.action = police->tcf_action,
 		.mtu = police->tcfp_mtu,
 		.burst = PSCHED_NS2TICKS(police->tcfp_burst),
-		.refcnt = police->tcf_refcnt - ref,
-		.bindcnt = police->tcf_bindcnt - bind,
+		.refcnt = atomic_read(&police->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&police->tcf_bindcnt) - bind,
 	};
 	struct tcf_t t;
 
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index ec986ae..64889a4 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -179,8 +179,8 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tc_sample opt = {
 		.index      = s->tcf_index,
 		.action     = s->tcf_action,
-		.refcnt     = s->tcf_refcnt - ref,
-		.bindcnt    = s->tcf_bindcnt - bind,
+		.refcnt     = atomic_read(&s->tcf_refcnt) - ref,
+		.bindcnt    = atomic_read(&s->tcf_bindcnt) - bind,
 	};
 	struct tcf_t t;
 
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index e7b57e5..ec7e397 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -148,8 +148,8 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tcf_defact *d = to_defact(a);
 	struct tc_defact opt = {
 		.index   = d->tcf_index,
-		.refcnt  = d->tcf_refcnt - ref,
-		.bindcnt = d->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&d->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
 		.action  = d->tcf_action,
 	};
 	struct tcf_t t;
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 59949d6..2b05e56 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -172,8 +172,8 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tcf_skbedit *d = to_skbedit(a);
 	struct tc_skbedit opt = {
 		.index   = d->tcf_index,
-		.refcnt  = d->tcf_refcnt - ref,
-		.bindcnt = d->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&d->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
 		.action  = d->tcf_action,
 	};
 	struct tcf_t t;
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index b642ad3..ca1ddf9 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -201,8 +201,8 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tcf_skbmod_params  *p = rtnl_dereference(d->skbmod_p);
 	struct tc_skbmod opt = {
 		.index   = d->tcf_index,
-		.refcnt  = d->tcf_refcnt - ref,
-		.bindcnt = d->tcf_bindcnt - bind,
+		.refcnt  = atomic_read(&d->tcf_refcnt) - ref,
+		.bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
 		.action  = d->tcf_action,
 	};
 	struct tcf_t t;
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 30c9627..158d472 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -250,8 +250,8 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tcf_tunnel_key_params *params;
 	struct tc_tunnel_key opt = {
 		.index    = t->tcf_index,
-		.refcnt   = t->tcf_refcnt - ref,
-		.bindcnt  = t->tcf_bindcnt - bind,
+		.refcnt   = atomic_read(&t->tcf_refcnt) - ref,
+		.bindcnt  = atomic_read(&t->tcf_bindcnt) - bind,
 	};
 	struct tcf_t tm;
 
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 16eb067..e2d7aab 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -208,8 +208,8 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
 	struct tcf_vlan *v = to_vlan(a);
 	struct tc_vlan opt = {
 		.index    = v->tcf_index,
-		.refcnt   = v->tcf_refcnt - ref,
-		.bindcnt  = v->tcf_bindcnt - bind,
+		.refcnt   = atomic_read(&v->tcf_refcnt) - ref,
+		.bindcnt  = atomic_read(&v->tcf_bindcnt) - bind,
 		.action   = v->tcf_action,
 		.v_action = v->tcfv_action,
 	};
-- 
1.8.3.1

^ permalink raw reply related

* [patch net v2 2/4] net/sched: Use action array instead of action list as parameter
From: Chris Mi @ 2017-10-16 11:18 UTC (permalink / raw)
  To: netdev; +Cc: jhs, lucasb, xiyou.wangcong, jiri, davem
In-Reply-To: <1508152718-28726-1-git-send-email-chrism@mellanox.com>

When destroying filters, actions should be destroyed first.
The pointers of each action are saved in an array. TC doesn't
use the array directly, but put all actions in a doubly linked
list and use that list as parameter.

There is no problem if each filter has its own actions. But if
some filters share the same action, when these filters are
destroyed, RCU callback fl_destroy_filter() may be called at the
same time. That means the same action's 'struct list_head list'
could be manipulated at the same time. It may point to an invalid
address so that system will panic.

This patch uses the action array directly to fix this issue.

Fixes commit in pre-git era.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Chris Mi <chrism@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 include/net/act_api.h |   7 ++--
 net/sched/act_api.c   | 103 +++++++++++++++++++++++++++++++-------------------
 net/sched/cls_api.c   |  18 +++------
 3 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index a469ab6..081a313 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -148,16 +148,17 @@ static inline int tcf_idr_release(struct tc_action *a, bool bind)
 int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
 int tcf_unregister_action(struct tc_action_ops *a,
 			  struct pernet_operations *ops);
-int tcf_action_destroy(struct list_head *actions, int bind);
+int tcf_action_destroy(struct tc_action **actions, int nr, int bind);
 int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
 		    int nr_actions, struct tcf_result *res);
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
 		    struct nlattr *est, char *name, int ovr, int bind,
-		    struct list_head *actions);
+		    struct tc_action **actions, int *nr);
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
 				    struct nlattr *nla, struct nlattr *est,
 				    char *name, int ovr, int bind);
-int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
+int tcf_action_dump(struct sk_buff *skb, struct tc_action **actions, int nr,
+		    int bind, int ref);
 int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 9c0224d..391d560 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -513,13 +513,15 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
 }
 EXPORT_SYMBOL(tcf_action_exec);
 
-int tcf_action_destroy(struct list_head *actions, int bind)
+int tcf_action_destroy(struct tc_action **actions, int nr, int bind)
 {
 	const struct tc_action_ops *ops;
-	struct tc_action *a, *tmp;
+	struct tc_action *a;
 	int ret = 0;
+	int i;
 
-	list_for_each_entry_safe(a, tmp, actions, list) {
+	for (i = 0; i < nr; i++) {
+		a = actions[i];
 		ops = a->ops;
 		ret = __tcf_idr_release(a, bind, true);
 		if (ret == ACT_P_DELETED)
@@ -568,14 +570,16 @@ int tcf_action_destroy(struct list_head *actions, int bind)
 }
 EXPORT_SYMBOL(tcf_action_dump_1);
 
-int tcf_action_dump(struct sk_buff *skb, struct list_head *actions,
+int tcf_action_dump(struct sk_buff *skb, struct tc_action **actions, int nr,
 		    int bind, int ref)
 {
 	struct tc_action *a;
-	int err = -EINVAL;
 	struct nlattr *nest;
+	int err = -EINVAL;
+	int i;
 
-	list_for_each_entry(a, actions, list) {
+	for (i = 0; i < nr; i++) {
+		a = actions[i];
 		nest = nla_nest_start(skb, a->order);
 		if (nest == NULL)
 			goto nla_put_failure;
@@ -700,10 +704,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
 	if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) {
 		err = tcf_action_goto_chain_init(a, tp);
 		if (err) {
-			LIST_HEAD(actions);
-
-			list_add_tail(&a->list, &actions);
-			tcf_action_destroy(&actions, bind);
+			tcf_action_destroy(&a, 1, bind);
 			return ERR_PTR(err);
 		}
 	}
@@ -720,23 +721,27 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
 	return ERR_PTR(err);
 }
 
-static void cleanup_a(struct list_head *actions, int ovr)
+static void cleanup_a(struct tc_action **actions, int nr, int ovr)
 {
 	struct tc_action *a;
+	int i;
 
 	if (!ovr)
 		return;
 
-	list_for_each_entry(a, actions, list)
+	for (i = 0; i < nr; i++) {
+		a = actions[i];
 		atomic_dec(&a->tcfa_refcnt);
+	}
 }
 
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
 		    struct nlattr *est, char *name, int ovr, int bind,
-		    struct list_head *actions)
+		    struct tc_action **actions, int *nr)
 {
 	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
 	struct tc_action *act;
+	int n = 0;
 	int err;
 	int i;
 
@@ -753,17 +758,19 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
 		act->order = i;
 		if (ovr)
 			atomic_inc(&act->tcfa_refcnt);
-		list_add_tail(&act->list, actions);
+		actions[n++] = act;
 	}
+	*nr = n;
 
 	/* Remove the temp refcnt which was necessary to protect against
 	 * destroying an existing action which was being replaced
 	 */
-	cleanup_a(actions, ovr);
+	cleanup_a(actions, n, ovr);
 	return 0;
 
 err:
-	tcf_action_destroy(actions, bind);
+	tcf_action_destroy(actions, n, bind);
+	*nr = 0;
 	return err;
 }
 
@@ -811,9 +818,9 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
 	return -1;
 }
 
-static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
-			u32 portid, u32 seq, u16 flags, int event, int bind,
-			int ref)
+static int tca_get_fill(struct sk_buff *skb, struct tc_action **actions,
+			int nr, u32 portid, u32 seq, u16 flags, int event,
+			int bind, int ref)
 {
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
@@ -832,7 +839,7 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
 	if (nest == NULL)
 		goto out_nlmsg_trim;
 
-	if (tcf_action_dump(skb, actions, bind, ref) < 0)
+	if (tcf_action_dump(skb, actions, nr, bind, ref) < 0)
 		goto out_nlmsg_trim;
 
 	nla_nest_end(skb, nest);
@@ -847,14 +854,14 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
 
 static int
 tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
-	       struct list_head *actions, int event)
+	       struct tc_action **actions, int nr, int event)
 {
 	struct sk_buff *skb;
 
 	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 	if (!skb)
 		return -ENOBUFS;
-	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
+	if (tca_get_fill(skb, actions, nr, portid, n->nlmsg_seq, 0, event,
 			 0, 0) <= 0) {
 		kfree_skb(skb);
 		return -EINVAL;
@@ -968,7 +975,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 }
 
 static int
-tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
+tcf_del_notify(struct net *net, struct nlmsghdr *n,
+	       struct tc_action **actions, int nr,
 	       u32 portid)
 {
 	int ret;
@@ -978,14 +986,14 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 	if (!skb)
 		return -ENOBUFS;
 
-	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
-			 0, 1) <= 0) {
+	if (tca_get_fill(skb, actions, nr, portid, n->nlmsg_seq, 0,
+			 RTM_DELACTION, 0, 1) <= 0) {
 		kfree_skb(skb);
 		return -EINVAL;
 	}
 
 	/* now do the delete */
-	ret = tcf_action_destroy(actions, 0);
+	ret = tcf_action_destroy(actions, nr, 0);
 	if (ret < 0) {
 		kfree_skb(skb);
 		return ret;
@@ -1002,10 +1010,11 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 	      u32 portid, int event)
 {
-	int i, ret;
 	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
+	struct tc_action **actions;
 	struct tc_action *act;
-	LIST_HEAD(actions);
+	int i, ret;
+	int nr = 0;
 
 	ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
 	if (ret < 0)
@@ -1018,6 +1027,11 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 			return -EINVAL;
 	}
 
+	actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
+			  GFP_KERNEL);
+	if (!actions)
+		return -ENOMEM;
+
 	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
 		act = tcf_action_get_1(net, tb[i], n, portid);
 		if (IS_ERR(act)) {
@@ -1025,25 +1039,28 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 			goto err;
 		}
 		act->order = i;
-		list_add_tail(&act->list, &actions);
+		actions[nr++] = act;
 	}
 
 	if (event == RTM_GETACTION)
-		ret = tcf_get_notify(net, portid, n, &actions, event);
+		ret = tcf_get_notify(net, portid, n, actions, nr, event);
 	else { /* delete */
-		ret = tcf_del_notify(net, n, &actions, portid);
+		ret = tcf_del_notify(net, n, actions, nr, portid);
 		if (ret)
 			goto err;
+		kfree(actions);
 		return ret;
 	}
 err:
 	if (event != RTM_GETACTION)
-		tcf_action_destroy(&actions, 0);
+		tcf_action_destroy(actions, nr, 0);
+	kfree(actions);
 	return ret;
 }
 
 static int
-tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
+tcf_add_notify(struct net *net, struct nlmsghdr *n,
+	       struct tc_action **actions, int nr,
 	       u32 portid)
 {
 	struct sk_buff *skb;
@@ -1053,7 +1070,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 	if (!skb)
 		return -ENOBUFS;
 
-	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
+	if (tca_get_fill(skb, actions, nr, portid, n->nlmsg_seq, n->nlmsg_flags,
 			 RTM_NEWACTION, 0, 0) <= 0) {
 		kfree_skb(skb);
 		return -EINVAL;
@@ -1069,14 +1086,24 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 static int tcf_action_add(struct net *net, struct nlattr *nla,
 			  struct nlmsghdr *n, u32 portid, int ovr)
 {
+	struct tc_action **actions;
 	int ret = 0;
-	LIST_HEAD(actions);
+	int nr;
 
-	ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, &actions);
+	actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
+			  GFP_KERNEL);
+	if (!actions)
+		return -ENOMEM;
+
+	ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0,
+			      actions, &nr);
 	if (ret)
-		return ret;
+		goto out;
 
-	return tcf_add_notify(net, n, &actions, portid);
+	ret = tcf_add_notify(net, n, actions, nr, portid);
+out:
+	kfree(actions);
+	return ret;
 }
 
 static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 0b2219a..acaa0c6 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -879,8 +879,7 @@ void tcf_exts_destroy(struct tcf_exts *exts)
 #ifdef CONFIG_NET_CLS_ACT
 	LIST_HEAD(actions);
 
-	tcf_exts_to_list(exts, &actions);
-	tcf_action_destroy(&actions, TCA_ACT_UNBIND);
+	tcf_action_destroy(exts->actions, exts->nr_actions, TCA_ACT_UNBIND);
 	kfree(exts->actions);
 	exts->nr_actions = 0;
 #endif
@@ -905,17 +904,14 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
 			exts->actions[0] = act;
 			exts->nr_actions = 1;
 		} else if (exts->action && tb[exts->action]) {
-			LIST_HEAD(actions);
-			int err, i = 0;
+			int err;
 
 			err = tcf_action_init(net, tp, tb[exts->action],
 					      rate_tlv, NULL, ovr, TCA_ACT_BIND,
-					      &actions);
+					      exts->actions,
+					      &exts->nr_actions);
 			if (err)
 				return err;
-			list_for_each_entry(act, &actions, list)
-				exts->actions[i++] = act;
-			exts->nr_actions = i;
 		}
 	}
 #else
@@ -961,14 +957,12 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts)
 		 * tc data even if iproute2  was newer - jhs
 		 */
 		if (exts->type != TCA_OLD_COMPAT) {
-			LIST_HEAD(actions);
-
 			nest = nla_nest_start(skb, exts->action);
 			if (nest == NULL)
 				goto nla_put_failure;
 
-			tcf_exts_to_list(exts, &actions);
-			if (tcf_action_dump(skb, &actions, 0, 0) < 0)
+			if (tcf_action_dump(skb, exts->actions,
+					    exts->nr_actions, 0, 0) < 0)
 				goto nla_put_failure;
 			nla_nest_end(skb, nest);
 		} else if (exts->police) {
-- 
1.8.3.1

^ permalink raw reply related

* [patch net v2 0/4] net/sched: Fix a system panic when deleting filters
From: Chris Mi @ 2017-10-16 11:18 UTC (permalink / raw)
  To: netdev; +Cc: jhs, lucasb, xiyou.wangcong, jiri, davem

If some filters share the same action, when deleting these filters,
it is possible to create a system panic. This is because deletions
could be manipulated by many RCU callbacks at the same time.

This patch set fixes these issues. To reproduce the issue run selftests
in patch 3 and 4. To test if the issue was fixed, apply patches 1 and 2
and then repeat the tests.

v2 changelog
============

Revise the comment and add Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

Chris Mi (4):
  net/sched: Change tc_action refcnt and bindcnt to atomic
  net/sched: Use action array instead of action list as parameter
  selftests: Introduce a new script to generate tc batch file
  selftests: Introduce a new test case to tc testsuite

 include/net/act_api.h                              |  11 +-
 net/sched/act_api.c                                | 124 +++++++++++++--------
 net/sched/act_bpf.c                                |   4 +-
 net/sched/act_connmark.c                           |   4 +-
 net/sched/act_csum.c                               |   4 +-
 net/sched/act_gact.c                               |   4 +-
 net/sched/act_ife.c                                |   4 +-
 net/sched/act_ipt.c                                |   4 +-
 net/sched/act_mirred.c                             |   4 +-
 net/sched/act_nat.c                                |   4 +-
 net/sched/act_pedit.c                              |   4 +-
 net/sched/act_police.c                             |   4 +-
 net/sched/act_sample.c                             |   4 +-
 net/sched/act_simple.c                             |   4 +-
 net/sched/act_skbedit.c                            |   4 +-
 net/sched/act_skbmod.c                             |   4 +-
 net/sched/act_tunnel_key.c                         |   4 +-
 net/sched/act_vlan.c                               |   4 +-
 net/sched/cls_api.c                                |  18 +--
 .../tc-testing/tc-tests/filters/tests.json         |  23 +++-
 tools/testing/selftests/tc-testing/tdc.py          |  20 +++-
 tools/testing/selftests/tc-testing/tdc_batch.py    |  62 +++++++++++
 tools/testing/selftests/tc-testing/tdc_config.py   |   2 +
 23 files changed, 222 insertions(+), 102 deletions(-)
 create mode 100755 tools/testing/selftests/tc-testing/tdc_batch.py

-- 
1.8.3.1

^ permalink raw reply

* Re: [patch net 0/4] net/sched: Fix a system panic when deleting filters
From: Jamal Hadi Salim @ 2017-10-16 11:06 UTC (permalink / raw)
  To: Chris Mi, netdev; +Cc: lucasb, xiyou.wangcong, jiri, davem
In-Reply-To: <1508142702-3312-1-git-send-email-chrism@mellanox.com>


Hi Chris,

On 17-10-16 04:31 AM, Chris Mi wrote:
> If some filters share the same action, when deleting these filters,
> system may panic. This patchset fixes this issue. And the test case
> finding this issue is also integrated into tc test suite of selftests.
>

I think this would read better if re-worded as:
---
If some filters share the same action, when deleting these filters,
it is possible to create a system panic. This is because deletions
could be manipulated by many RCU callbacks at the same time.
This patch set fixes these issues.
To reproduce the issue run selftests in patch 3 and 4.
To test if the issue was fixed, apply patches 1 and 2 and
then repeat the tests.
------

Other than that all look good to me and:

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply

* [PATCH net-next] dsa: slave: support phy devices on external MII bus
From: Martin Hundebøll @ 2017-10-16 10:45 UTC (permalink / raw)
  To: David S . Miller
  Cc: Martin Hundebøll, netdev, Andrew Lunn, Vivien Didelot,
	Florian Fainelli

When configuring a switch port to use an external phy, the phy is
connected to external switch MII bus:

                    +---------+
 +-----+  MII cpu   | Switch  |  MII ext   +-----+
 | CPU | ---------> |---------| ---------> | PHY |
 +-----+            | MII int |            +-----+
                    +---------+

In the device tree, the configuration looks something like this:

/ {
  /* ... */

  mdio {
    /* phy on MII cpu */
    phy0@0 {
      reg = <0>;
    };

    /* switch on MII cpu */
    switch0@1 {
      reg = <1>;

      ports {
        /* port internal phy */
        port1@1 {
          reg = <1>;
          label = "lan1";
          phy-handle <&switch0phy1>;
        };

        /* port with external phy */
        port0@0 {
          reg = <0>;
          label = "lan0";
          phy-handle <&switch0phy0>;
        };
      };

      /* internal MII */
      mdio {
        switch0phy1@1 {
          reg = <1>;
        };
      };

      /* external MII */
      mdio1 {
        switch0phy0: switch0phy0@0 {
          reg = <0>;
        };
      };
    };
  };

  /* ... */
};

When connecting port0 to switch0phy0, the current dsa code assumes the
phy to be connected to the internal MII bus, and thus fails with

    mv88e6085 f1072004.mdio-mii:02 lan0: no phy at 0
    mv88e6085 f1072004.mdio-mii:02 lan0: failed to connect to phy0: -19
    mvneta f1034000.ethernet eth2: error -19 setting up slave phy
    mv88e6085 f1072004.mdio-mii:02: Failed to create slave 0: -19

Fix this by using the phy of-handle to obtain a reference to the parent
mdio_bus, which is then used to connect the phy.

Signed-off-by: Martin Hundebøll <mnhu@prevas.dk>
---
 net/dsa/slave.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 45f4ea845c07..62ad69a728be 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -976,12 +976,16 @@ static int dsa_slave_fixed_link_update(struct net_device *dev,
 }
 
 /* slave device setup *******************************************************/
-static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr)
+static int dsa_slave_phy_connect(struct net_device *slave_dev,
+				 struct mii_bus *bus, int addr)
 {
 	struct dsa_slave_priv *p = netdev_priv(slave_dev);
 	struct dsa_switch *ds = p->dp->ds;
 
-	slave_dev->phydev = mdiobus_get_phy(ds->slave_mii_bus, addr);
+	if (!bus)
+		bus = ds->slave_mii_bus;
+
+	slave_dev->phydev = mdiobus_get_phy(bus, addr);
 	if (!slave_dev->phydev) {
 		netdev_err(slave_dev, "no phy at %d\n", addr);
 		return -ENODEV;
@@ -1029,6 +1033,7 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
 
 	if (phy_dn) {
 		int phy_id = of_mdio_parse_addr(&slave_dev->dev, phy_dn);
+		struct mii_bus *bus = of_mdio_find_bus(phy_dn->parent);
 
 		/* If this PHY address is part of phys_mii_mask, which means
 		 * that we need to divert reads and writes to/from it, then we
@@ -1037,7 +1042,7 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
 		 */
 		if (!phy_is_fixed && phy_id >= 0 &&
 		    (ds->phys_mii_mask & (1 << phy_id))) {
-			ret = dsa_slave_phy_connect(slave_dev, phy_id);
+			ret = dsa_slave_phy_connect(slave_dev, bus, phy_id);
 			if (ret) {
 				netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret);
 				of_node_put(phy_dn);
@@ -1061,7 +1066,7 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
 	 * MDIO bus instead
 	 */
 	if (!slave_dev->phydev) {
-		ret = dsa_slave_phy_connect(slave_dev, p->dp->index);
+		ret = dsa_slave_phy_connect(slave_dev, NULL, p->dp->index);
 		if (ret) {
 			netdev_err(slave_dev, "failed to connect to port %d: %d\n",
 				   p->dp->index, ret);
-- 
2.14.2

^ permalink raw reply related

* Re: [net-next 6/9] e1000e: fix buffer overrun while the I219 is processing DMA transactions
From: Neftin, Sasha @ 2017-10-16 10:39 UTC (permalink / raw)
  To: David Laight, 'Jeff Kirsher', davem@davemloft.net
  Cc: netdev@vger.kernel.org, nhorman@redhat.com, sassmann@redhat.com,
	jogreene@redhat.com
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6DD0090E17@AcuExch.aculab.com>

On 10/11/2017 12:07, David Laight wrote:
> From: Jeff Kirsher
>> Sent: 10 October 2017 18:22
>> Intel 100/200 Series Chipset platforms reduced the round-trip
>> latency for the LAN Controller DMA accesses, causing in some high
>> performance cases a buffer overrun while the I219 LAN Connected
>> Device is processing the DMA transactions. I219LM and I219V devices
>> can fall into unrecovered Tx hang under very stressfully UDP traffic
>> and multiple reconnection of Ethernet cable. This Tx hang of the LAN
>> Controller is only recovered if the system is rebooted. Slightly slow
>> down DMA access by reducing the number of outstanding requests.
>> This workaround could have an impact on TCP traffic performance
>> on the platform. Disabling TSO eliminates performance loss for TCP
>> traffic without a noticeable impact on CPU performance.
>>
>> Please, refer to I218/I219 specification update:
>> https://www.intel.com/content/www/us/en/embedded/products/networking/
>> ethernet-connection-i218-family-documentation.html
>>
>> Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
>> Reviewed-by: Dima Ruinskiy <dima.ruinskiy@intel.com>
>> Reviewed-by: Raanan Avargil <raanan.avargil@intel.com>
>> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> ---
>>   drivers/net/ethernet/intel/e1000e/netdev.c | 8 +++++---
>>   1 file changed, 5 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
>> index ee9de3500331..14b096f3d1da 100644
>> --- a/drivers/net/ethernet/intel/e1000e/netdev.c
>> +++ b/drivers/net/ethernet/intel/e1000e/netdev.c
>> @@ -3021,8 +3021,8 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
>>
>>   	hw->mac.ops.config_collision_dist(hw);
>>
>> -	/* SPT and CNP Si errata workaround to avoid data corruption */
>> -	if (hw->mac.type >= e1000_pch_spt) {
>> +	/* SPT and KBL Si errata workaround to avoid data corruption */
>> +	if (hw->mac.type == e1000_pch_spt) {
>>   		u32 reg_val;
>>
>>   		reg_val = er32(IOSFPC);
>> @@ -3030,7 +3030,9 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
>>   		ew32(IOSFPC, reg_val);
>>
>>   		reg_val = er32(TARC(0));
>> -		reg_val |= E1000_TARC0_CB_MULTIQ_3_REQ;
>> +		/* SPT and KBL Si errata workaround to avoid Tx hang */
>> +		reg_val &= ~BIT(28);
>> +		reg_val |= BIT(29);
> Shouldn't some more of the commit message about what this is doing
> be in the comment?
There is provided link on specification update: 
https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/i218-i219-ethernet-connection-spec-update.pdf?asset=9561. 
This is Intel's public release.
> And shouldn't the 28 and 28 be named constants?
(28 and 29) - you can easy understand from code that same value has been 
changed from 3 to 2. There is no point add flag here I thought.
>
>>   		ew32(TARC(0), reg_val);
> 	David
>
Thanks,

Sasha

^ permalink raw reply

* Re: [iproute2] regression in ss output
From: Phil Sutter @ 2017-10-16 10:33 UTC (permalink / raw)
  To: Humberto Alves; +Cc: netdev@vger.kernel.org, Stephen Hemminger
In-Reply-To: <AM4PR0901MB125261BF480B49D2BA2DF46BCC480@AM4PR0901MB1252.eurprd09.prod.outlook.com>

Hi,

On Fri, Oct 13, 2017 at 09:57:37AM +0000, Humberto Alves wrote:
> Hi! With the last iproute2 release, ss command output does not 
> differentiate between any-address IPv4 sockets from the IPv6 ones.
> I don't know if this is an expected behaviour, but the old output looks 
> more useful. Below I pasted the difference between the old behaviour and 
> the new one.

Although the change is certainly intentional (it was introduced by
Stephen Hemminger as a side effect of aba9c23a6e1cb ("ss: enclose IPv6
address in brackets"), I second reverting to the old display of
in6addr_any as '::'.

> I am happy to send a patch if you want. Thanks

It should be enough to just getting rid of the

| if (!memcmp(a->data, &in6addr_any, sizeof(in6addr_any))) {

case in inet_addr_print(). The else-case which calls format_host()
should deal with in6addr_any just fine. This way the address also gets
enclosed in brackets which helps separating it from the ':port' part.

Cheers, Phil

^ permalink raw reply

* Re: usb/net/rt2x00: warning in rt2800_eeprom_word_index
From: Kalle Valo @ 2017-10-16 10:27 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Stanislaw Gruszka, Andrey Konovalov, Helmut Schaa, linux-wireless,
	netdev, LKML, Kostya Serebryany, syzkaller
In-Reply-To: <CACT4Y+YLM-u7bMfRB=eu_pz1M9iDrY-Qmnho7Hw_Lh3M=LSeMQ@mail.gmail.com>

Dmitry Vyukov <dvyukov@google.com> writes:

> On Thu, Oct 12, 2017 at 9:25 AM, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
>> Hi
>>
>> On Mon, Oct 09, 2017 at 07:50:53PM +0200, Andrey Konovalov wrote:
>>> I've got the following report while fuzzing the kernel with syzkaller.
>>>
>>> On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).
>>>
>>> I'm not sure whether this is a bug in the driver, or just a way to
>>> report misbehaving device. In the latter case this shouldn't be a
>>> WARN() call, since WARN() means bug in the kernel.
>>
>> This is about wrong EEPROM, which reported 3 tx streams on
>> non 3 antenna device. I think WARN() is justified and thanks
>> to the call trace I was actually able to to understand what
>> happened.
>>
>> In general I do not think WARN() only means a kernel bug, it
>> can be F/W or H/W bug too.
>
> Hi Stanislaw,
>
> Printing messages is fine. Printing stacks is fine. Just please make
> them distinguishable from kernel bugs and don't kill the whole
> possibility of automated Linux kernel testing. That's an important
> capability.

Not really following you. Are you saying that using WARN() prevents
automated Linux kernel testing?

-- 
Kalle Valo

^ permalink raw reply


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