Netdev List
 help / color / mirror / Atom feed
* Re: KASAN: invalid-free in tls_sk_proto_cleanup
From: Jakub Kicinski @ 2019-07-31 22:46 UTC (permalink / raw)
  To: syzbot
  Cc: aviadye, borisp, daniel, davejwatson, davem, john.fastabend,
	linux-kernel, netdev, syzkaller-bugs
In-Reply-To: <00000000000010fb45058ef5eb52@google.com>

On Wed, 31 Jul 2019 01:29:05 -0700, syzbot wrote:
> Hello,
> 
> syzbot found the following crash on:
> 
> HEAD commit:    fde50b96 Add linux-next specific files for 20190726
> git tree:       linux-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=15ea7f3fa00000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=4b58274564b354c1
> dashboard link: https://syzkaller.appspot.com/bug?extid=f5731e2256eb5130dbd6
> compiler:       gcc (GCC) 9.0.0 20181231 (experimental)
> 
> Unfortunately, I don't have any reproducer for this crash yet.
> 
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+f5731e2256eb5130dbd6@syzkaller.appspotmail.com
> 
> ==================================================================
> BUG: KASAN: double-free or invalid-free in tls_sk_proto_cleanup+0x216/0x3e0  
> net/tls/tls_main.c:300

FWIW there is a fix in the works for this and all new TLS issues.
I think John and Eric didn't have time yet to look at my theories,
so I'd like to keep it in QA for one extra day before posting.

^ permalink raw reply

* Re: [pull request][net-next 00/13] Mellanox, mlx5 tc flow handling for concurrent execution (Part 1)
From: David Miller @ 2019-07-31 22:48 UTC (permalink / raw)
  To: saeedm; +Cc: netdev
In-Reply-To: <20190729234934.23595-1-saeedm@mellanox.com>

From: Saeed Mahameed <saeedm@mellanox.com>
Date: Mon, 29 Jul 2019 23:50:14 +0000

> This series, mostly from Vlad, is the first part of ongoing work to
> improve mlx5 tc flow handling by removing dependency on rtnl_lock and
> providing a more fine-grained locking and rcu safe data structures.
> 
> For more information please see tag log below.
> 
> Please pull and let me know if there is any problem.

Pulled, thanks Saeed.

I will push this back out after a build test (which will take a while
since I am on my laptop).  So please be patient.

Thanks.

^ permalink raw reply

* [PATCH net v3] net: bridge: move vlan init/deinit to NETDEV_REGISTER/UNREGISTER
From: Nikolay Aleksandrov @ 2019-07-31 22:49 UTC (permalink / raw)
  To: netdev; +Cc: roopa, davem, bridge, Nikolay Aleksandrov, michael-dev
In-Reply-To: <319fda43-195d-2b92-7f62-7e273c084a29@cumulusnetworks.com>

Most of the bridge device's vlan init bugs come from the fact that it's
done in the wrong place, way too early in ndo_init() before the device is
even assigned an ifindex. That makes error handling harder, especially for
older kernels which don't have bridge ndo_uninit callback. It also
introduces another bug when the bridge's dev_addr is added as fdb in the
the initial default pvid on vlan initialization, the fdb notification has
ifindex/NDA_MASTER both equal to 0 (see example below) which really
makes no sense for user-space[0]. Usually user-space software would ignore
such entries, but they are actually valid and will eventually have all
necessary attributes. I chose to change the order because this can be
backported to all kernels even pre-ndo_uninit ones without many changes
and it keeps init/deinit symmetric. As a bonus this allows us to keep
the vlan init/deinit entirely in br_vlan.c and remove those exports.
It makes much more sense to send a notification *after* the device has
registered and has a proper ifindex allocated rather than before when
there's a chance that the registration might still fail.

For the demonstration below a small change to iproute2 for printing all fdb
notifications is added, because it contained a workaround not to show
entries with ifindex == 0.
Command executed while monitoring: $ ip l add br0 type bridge
Before (both ifindex and master == 0):
$ bridge monitor fdb
36:7e:8a:b3:56:ba dev * vlan 1 master * permanent

After (proper br0 ifindex):
$ bridge monitor fdb
e6:2a:ae:7a:b7:48 dev br0 vlan 1 master br0 permanent

v3: send the correct v2 patch with all changes (stub should return 0)
v2: on error in br_vlan_init set br->vlgrp to NULL and return 0 in
    the br_vlan_bridge_event stub when bridge vlans are disabled

[0] https://bugzilla.kernel.org/show_bug.cgi?id=204389

Reported-by: michael-dev <michael-dev@fami-braun.de>
Fixes: 5be5a2df40f0 ("bridge: Add filtering support for default_pvid")
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
I tried a few different approaches to resolve this but they were all
unsuitable for some kernels, this approach can go to stables easily
and IMO is the way this had to be done from the start. Alternatively
we could move only the br_vlan_add and pair it with a br_vlan_del of
default_pvid on the same events, but I don't think it hurts to move
the whole init/deinit there as it'd help older stable releases as well.

I also tested the br_vlan_init error handling after the move by always
returning errors from all over it. Since errors at NETDEV_REGISTER cause
NETDEV_UNREGISTER we can deinit vlans properly for all cases regardless
why it happened (e.g. device destruction or init error).

 net/bridge/br.c         |  5 ++++-
 net/bridge/br_device.c  | 10 ----------
 net/bridge/br_private.h | 20 +++++---------------
 net/bridge/br_vlan.c    | 25 ++++++++++++++++++-------
 4 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/net/bridge/br.c b/net/bridge/br.c
index d164f63a4345..8a8f9e5f264f 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -37,12 +37,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
 	int err;
 
 	if (dev->priv_flags & IFF_EBRIDGE) {
+		err = br_vlan_bridge_event(dev, event, ptr);
+		if (err)
+			return notifier_from_errno(err);
+
 		if (event == NETDEV_REGISTER) {
 			/* register of bridge completed, add sysfs entries */
 			br_sysfs_addbr(dev);
 			return NOTIFY_DONE;
 		}
-		br_vlan_bridge_event(dev, event, ptr);
 	}
 
 	/* not a port of a bridge */
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 681b72862c16..b3e3de2ecf95 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -135,18 +135,9 @@ static int br_dev_init(struct net_device *dev)
 		return err;
 	}
 
-	err = br_vlan_init(br);
-	if (err) {
-		free_percpu(br->stats);
-		br_mdb_hash_fini(br);
-		br_fdb_hash_fini(br);
-		return err;
-	}
-
 	err = br_multicast_init_stats(br);
 	if (err) {
 		free_percpu(br->stats);
-		br_vlan_flush(br);
 		br_mdb_hash_fini(br);
 		br_fdb_hash_fini(br);
 	}
@@ -161,7 +152,6 @@ static void br_dev_uninit(struct net_device *dev)
 
 	br_multicast_dev_del(br);
 	br_multicast_uninit_stats(br);
-	br_vlan_flush(br);
 	br_mdb_hash_fini(br);
 	br_fdb_hash_fini(br);
 	free_percpu(br->stats);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e8cf03b43b7d..782f18c6b2a9 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -872,7 +872,6 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
 int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags,
 		bool *changed, struct netlink_ext_ack *extack);
 int br_vlan_delete(struct net_bridge *br, u16 vid);
-void br_vlan_flush(struct net_bridge *br);
 struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid);
 void br_recalculate_fwd_mask(struct net_bridge *br);
 int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
@@ -881,7 +880,6 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto);
 int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
 int br_vlan_set_stats(struct net_bridge *br, unsigned long val);
 int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val);
-int br_vlan_init(struct net_bridge *br);
 int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
 int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,
 			       struct netlink_ext_ack *extack);
@@ -894,8 +892,8 @@ int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
 void br_vlan_get_stats(const struct net_bridge_vlan *v,
 		       struct br_vlan_stats *stats);
 void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
-			  void *ptr);
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
+			 void *ptr);
 
 static inline struct net_bridge_vlan_group *br_vlan_group(
 					const struct net_bridge *br)
@@ -988,19 +986,10 @@ static inline int br_vlan_delete(struct net_bridge *br, u16 vid)
 	return -EOPNOTSUPP;
 }
 
-static inline void br_vlan_flush(struct net_bridge *br)
-{
-}
-
 static inline void br_recalculate_fwd_mask(struct net_bridge *br)
 {
 }
 
-static inline int br_vlan_init(struct net_bridge *br)
-{
-	return 0;
-}
-
 static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
 			       bool *changed, struct netlink_ext_ack *extack)
 {
@@ -1085,9 +1074,10 @@ static inline void br_vlan_port_event(struct net_bridge_port *p,
 {
 }
 
-static inline void br_vlan_bridge_event(struct net_device *dev,
-					unsigned long event, void *ptr)
+static inline int br_vlan_bridge_event(struct net_device *dev,
+				       unsigned long event, void *ptr)
 {
+	return 0;
 }
 #endif
 
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index a544e161c7fa..6a17408b4eb8 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -709,7 +709,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
 	return __vlan_del(v);
 }
 
-void br_vlan_flush(struct net_bridge *br)
+static void br_vlan_flush(struct net_bridge *br)
 {
 	struct net_bridge_vlan_group *vg;
 
@@ -721,6 +721,8 @@ void br_vlan_flush(struct net_bridge *br)
 	br_fdb_delete_by_port(br, NULL, 0, 1);
 
 	vg = br_vlan_group(br);
+	if (!vg)
+		return;
 	__vlan_flush(vg);
 	RCU_INIT_POINTER(br->vlgrp, NULL);
 	synchronize_rcu();
@@ -1054,7 +1056,7 @@ int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
 	return err;
 }
 
-int br_vlan_init(struct net_bridge *br)
+static int br_vlan_init(struct net_bridge *br)
 {
 	struct net_bridge_vlan_group *vg;
 	int ret = -ENOMEM;
@@ -1083,6 +1085,8 @@ int br_vlan_init(struct net_bridge *br)
 	return ret;
 
 err_vlan_add:
+	RCU_INIT_POINTER(br->vlgrp, NULL);
+	synchronize_rcu();
 	vlan_tunnel_deinit(vg);
 err_tunnel_init:
 	rhashtable_destroy(&vg->vlan_hash);
@@ -1469,13 +1473,19 @@ static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid)
 }
 
 /* Must be protected by RTNL. */
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
-			  void *ptr)
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr)
 {
 	struct netdev_notifier_changeupper_info *info;
-	struct net_bridge *br;
+	struct net_bridge *br = netdev_priv(dev);
+	int ret = 0;
 
 	switch (event) {
+	case NETDEV_REGISTER:
+		ret = br_vlan_init(br);
+		break;
+	case NETDEV_UNREGISTER:
+		br_vlan_flush(br);
+		break;
 	case NETDEV_CHANGEUPPER:
 		info = ptr;
 		br_vlan_upper_change(dev, info->upper_dev, info->linking);
@@ -1483,12 +1493,13 @@ void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
 
 	case NETDEV_CHANGE:
 	case NETDEV_UP:
-		br = netdev_priv(dev);
 		if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING))
-			return;
+			break;
 		br_vlan_link_state_change(dev, br);
 		break;
 	}
+
+	return ret;
 }
 
 /* Must be protected by RTNL. */
-- 
2.21.0


^ permalink raw reply related

* Re: [PATCH] tipc: compat: allow tipc commands without arguments
From: David Miller @ 2019-07-31 22:52 UTC (permalink / raw)
  To: takondra
  Cc: jon.maloy, ying.xue, netdev, tipc-discussion, linux-kernel,
	xe-linux-external, stable
In-Reply-To: <20190729221507.48893-1-takondra@cisco.com>


Jon et al., please review.

Thank you.

^ permalink raw reply

* Re: [PATCH 00/14] ARM: move lpc32xx and dove to multiplatform
From: Russell King - ARM Linux admin @ 2019-07-31 22:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: soc, linux-arm-kernel, Vladimir Zapolskiy, Sylvain Lemieux,
	Gregory Clement, Linus Walleij, Jason Cooper, Andrew Lunn,
	Sebastian Hesselbarth, David S. Miller, Greg Kroah-Hartman,
	Alan Stern, Guenter Roeck, linux-gpio, netdev, linux-serial,
	linux-usb, linux-watchdog
In-Reply-To: <20190731195713.3150463-1-arnd@arndb.de>

On Wed, Jul 31, 2019 at 09:56:42PM +0200, Arnd Bergmann wrote:
> For dove, the patches are basically what I had proposed back in
> 2015 when all other ARMv6/ARMv7 machines became part of a single
> kernel build. I don't know what the state is mach-dove support is,
> compared to the DT based support in mach-mvebu for the same
> hardware. If they are functionally the same, we could also just
> remove mach-dove rather than applying my patches.

Well, the good news is that I'm down to a small board support file
for the Dove Cubox now - but the bad news is, that there's still a
board support file necessary to support everything the Dove SoC has
to offer.

Even for a DT based Dove Cubox, I'm still using mach-dove, but it
may be possible to drop most of mach-dove now.  Without spending a
lot of time digging through it, it's impossible to really know.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply

* Re: [PATCH net v3] net: bridge: move vlan init/deinit to NETDEV_REGISTER/UNREGISTER
From: Stephen Hemminger @ 2019-07-31 22:53 UTC (permalink / raw)
  To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge, michael-dev
In-Reply-To: <20190731224955.10908-1-nikolay@cumulusnetworks.com>

  
> -int br_vlan_init(struct net_bridge *br)
> +static int br_vlan_init(struct net_bridge *br)
>  {
>  	struct net_bridge_vlan_group *vg;
>  	int ret = -ENOMEM;
> @@ -1083,6 +1085,8 @@ int br_vlan_init(struct net_bridge *br)
>  	return ret;
>  
>  err_vlan_add:
> +	RCU_INIT_POINTER(br->vlgrp, NULL);
> +	synchronize_rcu();

Calling sychronize_rcu is expensive. And the callback for
notifier is always called with rtnl_head. 

Why not just keep the pointer initialization back in the
code where bridge is created, it was safe there.

^ permalink raw reply

* Re: [PATCH net] selftests/tls: fix TLS tests with CONFIG_TLS=n
From: David Miller @ 2019-07-31 22:54 UTC (permalink / raw)
  To: jakub.kicinski; +Cc: netdev, oss-drivers, rong.a.chen
In-Reply-To: <20190729230803.10781-1-jakub.kicinski@netronome.com>

From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Mon, 29 Jul 2019 16:08:03 -0700

> Build bot reports some recent TLS tests are failing
> with CONFIG_TLS=n. Correct the expected return code
> and skip TLS installation if not supported.
> 
> Tested with CONFIG_TLS=n and CONFIG_TLS=m.
> 
> Reported-by: kernel test robot <rong.a.chen@intel.com>
> Fixes: cf32526c8842 ("selftests/tls: add a test for ULP but no keys")
> Fixes: 65d41fb317c6 ("selftests/tls: add a bidirectional test")
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>

Applied, thanks Jakub.

^ permalink raw reply

* Re: [PATCH v2 net-next 1/1] tc-testing: Clarify the use of tdc's -d option
From: David Miller @ 2019-07-31 22:54 UTC (permalink / raw)
  To: lucasb
  Cc: netdev, nicolas.dichtel, jhs, xiyou.wangcong, jiri, mleitner,
	vladbu, dcaratti, kernel
In-Reply-To: <1564442292-4731-1-git-send-email-lucasb@mojatatu.com>

From: Lucas Bates <lucasb@mojatatu.com>
Date: Mon, 29 Jul 2019 19:18:12 -0400

> The -d command line argument to tdc requires the name of a physical device
> on the system where the tests will be run. If -d has not been used, tdc
> will skip tests that require a physical device.
> 
> This patch is intended to better document what the -d option does and how
> it is used.
> 
> Signed-off-by: Lucas Bates <lucasb@mojatatu.com>

Applied.

^ permalink raw reply

* Re: [PATCH v2] net: phy: phy_led_triggers: Fix a possible null-pointer dereference in phy_led_trigger_change_speed()
From: David Miller @ 2019-07-31 22:57 UTC (permalink / raw)
  To: baijiaju1990; +Cc: andrew, f.fainelli, hkallweit1, netdev, linux-kernel
In-Reply-To: <20190730080813.15363-1-baijiaju1990@gmail.com>

From: Jia-Ju Bai <baijiaju1990@gmail.com>
Date: Tue, 30 Jul 2019 16:08:13 +0800

> In phy_led_trigger_change_speed(), there is an if statement on line 48
> to check whether phy->last_triggered is NULL: 
>     if (!phy->last_triggered)
> 
> When phy->last_triggered is NULL, it is used on line 52:
>     led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
> 
> Thus, a possible null-pointer dereference may occur.
> 
> To fix this bug, led_trigger_event(&phy->last_triggered->trigger,
> LED_OFF) is called when phy->last_triggered is not NULL.
> 
> This bug is found by a static analysis tool STCheck written by
> the OSLAB group in Tsinghua University.
> 
> Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH nf,v2] netfilter: nf_tables: map basechain priority to hardware priority
From: Jakub Kicinski @ 2019-07-31 22:57 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: netfilter-devel, marcelo.leitner, wenxu, jiri, saeedm, gerlitz.or,
	paulb, netdev
In-Reply-To: <20190731121656.27951-1-pablo@netfilter.org>

On Wed, 31 Jul 2019 14:16:56 +0200, Pablo Neira Ayuso wrote:
> This patch adds initial support for offloading basechains using the
> priority range from -8192 to 8191.
> 
> The software priority -8192 is mapped to the hardware priority
> 0xC000 + 1. tcf_auto_prio() uses 0xC000 if the user specifies no
> priority, then it subtracts 1 for each new tcf_proto object. This patch
> reserves the hardware priority range from 0xC000 to 0xFFFF for
> netfilter.
> 
> The software to hardware priority mapping is not exposed to userspace,
> so it should be possible to update this / extend the range of supported
> priorities later on.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

I don't know the nft code, so perhaps my question on v1
was nonsensical, nonetheless I'd appreciate a response.
NFT referring to tcf_auto_prio() is a bit of a red flag.

^ permalink raw reply

* Re: [patch net-next v2 0/3] net: devlink: Finish network namespace support
From: David Miller @ 2019-07-31 22:59 UTC (permalink / raw)
  To: jiri; +Cc: netdev, jakub.kicinski, sthemmin, dsahern, mlxsw
In-Reply-To: <20190730085734.31504-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@resnulli.us>
Date: Tue, 30 Jul 2019 10:57:31 +0200

> Devlink from the beginning counts with network namespaces, but the
> instances has been fixed to init_net. The first patch allows user
> to move existing devlink instances into namespaces:
 ...

I read this thread and see there will be a v3.

^ permalink raw reply

* Re: [PATCH net] net: bridge: mcast: don't delete permanent entries when fast leave is enabled
From: David Miller @ 2019-07-31 23:04 UTC (permalink / raw)
  To: nikolay; +Cc: netdev, roopa, bridge
In-Reply-To: <20190730112100.18156-1-nikolay@cumulusnetworks.com>

From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Date: Tue, 30 Jul 2019 14:21:00 +0300

> When permanent entries were introduced by the commit below, they were
> exempt from timing out and thus igmp leave wouldn't affect them unless
> fast leave was enabled on the port which was added before permanent
> entries existed. It shouldn't matter if fast leave is enabled or not
> if the user added a permanent entry it shouldn't be deleted on igmp
> leave.
 ...
> Fixes: ccb1c31a7a87 ("bridge: add flags to distinguish permanent mdb entires")
> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

Applied and queued up for -stable.

^ permalink raw reply

* Re: [PATCH net-next] be2net: disable bh with spin_lock in be_process_mcc
From: David Miller @ 2019-07-31 23:08 UTC (permalink / raw)
  To: kda; +Cc: sathya.perla, ajit.khaparde, sriharsha.basavapatna, netdev, kdav
In-Reply-To: <20190730113226.39845-1-dkirjanov@suse.com>

From: Denis Kirjanov <kda@linux-powerpc.org>
Date: Tue, 30 Jul 2019 13:32:26 +0200

> Signed-off-by: Denis Kirjanov <kdav@linux-powerpc.org>

Empty commit message, no way.

You must explain what this patch is doing, and why.

^ permalink raw reply

* Re: [PATCH] net: stmmac: Use netif_tx_napi_add() for TX polling function
From: David Miller @ 2019-07-31 23:10 UTC (permalink / raw)
  To: brgl
  Cc: peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	netdev, linux-stm32, linux-arm-kernel, linux-kernel, fisaksen,
	bgolaszewski
In-Reply-To: <20190730113814.13825-1-brgl@bgdev.pl>

From: Bartosz Golaszewski <brgl@bgdev.pl>
Date: Tue, 30 Jul 2019 13:38:14 +0200

> From: Frode Isaksen <fisaksen@baylibre.com>
> 
> This variant of netif_napi_add() should be used from drivers
> using NAPI to exclusively poll a TX queue.
> 
> Signed-off-by: Frode Isaksen <fisaksen@baylibre.com>
> Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Applied and queued up for -stable.

^ permalink raw reply

* Re: [PATCH net-next] net: bridge: mcast: add delete due to fast-leave mdb flag
From: David Miller @ 2019-07-31 23:13 UTC (permalink / raw)
  To: nikolay; +Cc: netdev, roopa, bridge
In-Reply-To: <20190730122041.14647-1-nikolay@cumulusnetworks.com>

From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Date: Tue, 30 Jul 2019 15:20:41 +0300

> In user-space there's no way to distinguish why an mdb entry was deleted
> and that is a problem for daemons which would like to keep the mdb in
> sync with remote ends (e.g. mlag) but would also like to converge faster.
> In almost all cases we'd like to age-out the remote entry for performance
> and convergence reasons except when fast-leave is enabled. In that case we
> want explicit immediate remote delete, thus add mdb flag which is set only
> when the entry is being deleted due to fast-leave.
> 
> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

Applied, thanks Nikolay.

^ permalink raw reply

* Re: [PATCH net v3] net: bridge: move vlan init/deinit to NETDEV_REGISTER/UNREGISTER
From: Nikolay Aleksandrov @ 2019-07-31 23:32 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, roopa, davem, bridge, michael-dev
In-Reply-To: <20190731155338.15ff34cb@hermes.lan>

On 8/1/19 1:53 AM, Stephen Hemminger wrote:
>   
>> -int br_vlan_init(struct net_bridge *br)
>> +static int br_vlan_init(struct net_bridge *br)
>>  {
>>  	struct net_bridge_vlan_group *vg;
>>  	int ret = -ENOMEM;
>> @@ -1083,6 +1085,8 @@ int br_vlan_init(struct net_bridge *br)
>>  	return ret;
>>  
>>  err_vlan_add:
>> +	RCU_INIT_POINTER(br->vlgrp, NULL);
>> +	synchronize_rcu();
> 
> Calling sychronize_rcu is expensive. And the callback for
> notifier is always called with rtnl_head. 
> 
> Why not just keep the pointer initialization back in the
> code where bridge is created, it was safe there.
> 

Because now the device registered and we've published the group, right now
it is not an issue but if we expose an rcu helper we'll have to fix this
because it'd become a bug.
I'd prefer to have the error path correct and future-proof it, since it's
an error path we're not concerned with speed, but rather correctness. Also
these are rarely exercised so the bug might remain for a very long time.



^ permalink raw reply

* Re: [PATCH net v3] net: bridge: move vlan init/deinit to NETDEV_REGISTER/UNREGISTER
From: Nikolay Aleksandrov @ 2019-07-31 23:36 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, roopa, davem, bridge, michael-dev
In-Reply-To: <c9a68f85-49f6-6d02-e130-a03d540aa0a7@cumulusnetworks.com>

On 8/1/19 2:32 AM, Nikolay Aleksandrov wrote:
> On 8/1/19 1:53 AM, Stephen Hemminger wrote:
>>   
>>> -int br_vlan_init(struct net_bridge *br)
>>> +static int br_vlan_init(struct net_bridge *br)
>>>  {
>>>  	struct net_bridge_vlan_group *vg;
>>>  	int ret = -ENOMEM;
>>> @@ -1083,6 +1085,8 @@ int br_vlan_init(struct net_bridge *br)
>>>  	return ret;
>>>  
>>>  err_vlan_add:
>>> +	RCU_INIT_POINTER(br->vlgrp, NULL);
>>> +	synchronize_rcu();
>>
>> Calling sychronize_rcu is expensive. And the callback for
>> notifier is always called with rtnl_head. 
>>
>> Why not just keep the pointer initialization back in the
>> code where bridge is created, it was safe there.
>>
> 
> Because now the device registered and we've published the group, right now
> it is not an issue but if we expose an rcu helper we'll have to fix this
> because it'd become a bug.
> I'd prefer to have the error path correct and future-proof it, since it's
> an error path we're not concerned with speed, but rather correctness. Also
> these are rarely exercised so the bug might remain for a very long time.
> 
> 

About why move it - I've explained in the commit message, it might be safe
but it has presented a lot of bugs, we'll have to separate it in two parts
one that initializes the vlan group and second one which adds the fdb, then
we'll have to split the flush/delete in two different places to cleanup.
This way we have only a single exit point that cleans up and it works for
all cases. The synchronize there wouldn't be called under normal circumstances.




^ permalink raw reply

* Re: [PATCH] net: mdio-octeon: Fix build error and Kconfig warning
From: Randy Dunlap @ 2019-07-31 23:52 UTC (permalink / raw)
  To: Nathan Chancellor, davem
  Cc: andrew, broonie, devel, f.fainelli, gregkh, hkallweit1,
	kernel-build-reports, linux-arm-kernel, linux-next, netdev, willy,
	kbuild test robot
In-Reply-To: <b3444283-7a77-ece8-7ac6-41756aa7dc60@infradead.org>

On 7/31/19 2:55 PM, Randy Dunlap wrote:
> On 7/31/19 11:50 AM, Nathan Chancellor wrote:
>> arm allyesconfig warns:
>>
>> WARNING: unmet direct dependencies detected for MDIO_OCTEON
>>   Depends on [n]: NETDEVICES [=y] && MDIO_DEVICE [=y] && MDIO_BUS [=y]
>> && 64BIT && HAS_IOMEM [=y] && OF_MDIO [=y]
>>   Selected by [y]:
>>   - OCTEON_ETHERNET [=y] && STAGING [=y] && (CAVIUM_OCTEON_SOC &&
>> NETDEVICES [=y] || COMPILE_TEST [=y])
>>
>> and errors:
>>
>> In file included from ../drivers/net/phy/mdio-octeon.c:14:
>> ../drivers/net/phy/mdio-octeon.c: In function 'octeon_mdiobus_probe':
>> ../drivers/net/phy/mdio-cavium.h:111:36: error: implicit declaration of
>> function 'writeq'; did you mean 'writeb'?
>> [-Werror=implicit-function-declaration]
>>   111 | #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
>>       |                                    ^~~~~~
>> ../drivers/net/phy/mdio-octeon.c:56:2: note: in expansion of macro
>> 'oct_mdio_writeq'
>>    56 |  oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
>>       |  ^~~~~~~~~~~~~~~
>> cc1: some warnings being treated as errors
>>
>> This allows MDIO_OCTEON to be built with COMPILE_TEST as well and
>> includes the proper header for readq/writeq. This does not address
>> the several -Wint-to-pointer-cast and -Wpointer-to-int-cast warnings
>> that appeared as a result of commit 171a9bae68c7 ("staging/octeon:
>> Allow test build on !MIPS") in these files.
>>
>> Fixes: 171a9bae68c7 ("staging/octeon: Allow test build on !MIPS")
>> Reported-by: kbuild test robot <lkp@intel.com>
>> Reported-by: Mark Brown <broonie@kernel.org>
>> Reported-by: Randy Dunlap <rdunlap@infradead.org>
>> Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> 
> 
> With today's linux-next (20190731), I am still seeing a Kconfig warning and
> build errors (building for i386):
> 
> and applying Greg's "depends on NETDEVICES" patch and this patch:
> 
> WARNING: unmet direct dependencies detected for MDIO_OCTEON
>   Depends on [n]: NETDEVICES [=y] && MDIO_DEVICE [=m] && MDIO_BUS [=m] && (64BIT [=n] || COMPILE_TEST [=y]) && HAS_IOMEM [=y] && OF_MDIO [=n]
>   Selected by [m]:
>   - OCTEON_ETHERNET [=m] && STAGING [=y] && (CAVIUM_OCTEON_SOC || COMPILE_TEST [=y]) && NETDEVICES [=y]
> 
> ERROR: "cavium_mdiobus_write" [drivers/net/phy/mdio-octeon.ko] undefined!
> ERROR: "cavium_mdiobus_read" [drivers/net/phy/mdio-octeon.ko] undefined!
> 
> 
> kernel .config file is attached.
> 
> Am I missing another patch?
> 
> thanks.

If I add this to drivers/staging/octeon/Kconfig:
	select MDIO_OCTEON
+	select MDIO_CAVIUM
	help

then the build succeeds.

This isn't being done by make *config because MDIO_OCTEON depends on OF_MDIO,
which is not set in my .config file, so the "select MDIO_CAVIUM" in MDIO_OCTEON
is not done.

However, there are lots of type/cast warnings in both mdio-octeon and mdio-cavium:

../drivers/net/phy/mdio-octeon.c: In function ‘octeon_mdiobus_probe’:
../drivers/net/phy/mdio-octeon.c:48:3: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   (u64)devm_ioremap(&pdev->dev, mdio_phys, regsize);
   ^
In file included from ../drivers/net/phy/mdio-octeon.c:14:0:
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-octeon.c:56:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-octeon.c:77:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-octeon.c: In function ‘octeon_mdiobus_remove’:
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-octeon.c:91:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
  ^~~~~~~~~~~~~~~

and

  CC [M]  drivers/net/phy/mdio-cavium.o
In file included from ../drivers/net/phy/mdio-cavium.c:11:0:
../drivers/net/phy/mdio-cavium.c: In function ‘cavium_mdiobus_set_mode’:
../drivers/net/phy/mdio-cavium.h:114:37: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_readq(addr)  readq((void *)addr)
                                     ^
../drivers/net/phy/mdio-cavium.c:21:16: note: in expansion of macro ‘oct_mdio_readq’
  smi_clk.u64 = oct_mdio_readq(p->register_base + SMI_CLK);
                ^~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-cavium.c:24:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_clk.u64, p->register_base + SMI_CLK);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.c: In function ‘cavium_mdiobus_c45_addr’:
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-cavium.c:39:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-cavium.c:47:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:114:37: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_readq(addr)  readq((void *)addr)
                                     ^
../drivers/net/phy/mdio-cavium.c:54:16: note: in expansion of macro ‘oct_mdio_readq’
   smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
                ^~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.c: In function ‘cavium_mdiobus_read’:
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-cavium.c:86:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:114:37: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_readq(addr)  readq((void *)addr)
                                     ^
../drivers/net/phy/mdio-cavium.c:93:16: note: in expansion of macro ‘oct_mdio_readq’
   smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT);
                ^~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.c: In function ‘cavium_mdiobus_write’:
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-cavium.c:125:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:113:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr)
                                                ^
../drivers/net/phy/mdio-cavium.c:131:2: note: in expansion of macro ‘oct_mdio_writeq’
  oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
  ^~~~~~~~~~~~~~~
../drivers/net/phy/mdio-cavium.h:114:37: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 #define oct_mdio_readq(addr)  readq((void *)addr)
                                     ^
../drivers/net/phy/mdio-cavium.c:138:16: note: in expansion of macro ‘oct_mdio_readq’
   smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
                ^~~~~~~~~~~~~~




>> ---
>>  drivers/net/phy/Kconfig       | 2 +-
>>  drivers/net/phy/mdio-cavium.h | 2 ++
>>  2 files changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
>> index 20f14c5fbb7e..ed2edf4b5b0e 100644
>> --- a/drivers/net/phy/Kconfig
>> +++ b/drivers/net/phy/Kconfig
>> @@ -159,7 +159,7 @@ config MDIO_MSCC_MIIM
>>  
>>  config MDIO_OCTEON
>>  	tristate "Octeon and some ThunderX SOCs MDIO buses"
>> -	depends on 64BIT
>> +	depends on 64BIT || COMPILE_TEST
>>  	depends on HAS_IOMEM && OF_MDIO
>>  	select MDIO_CAVIUM
>>  	help
>> diff --git a/drivers/net/phy/mdio-cavium.h b/drivers/net/phy/mdio-cavium.h
>> index ed5f9bb5448d..b7f89ad27465 100644
>> --- a/drivers/net/phy/mdio-cavium.h
>> +++ b/drivers/net/phy/mdio-cavium.h
>> @@ -108,6 +108,8 @@ static inline u64 oct_mdio_readq(u64 addr)
>>  	return cvmx_read_csr(addr);
>>  }
>>  #else
>> +#include <linux/io-64-nonatomic-lo-hi.h>
>> +
>>  #define oct_mdio_writeq(val, addr)	writeq(val, (void *)addr)
>>  #define oct_mdio_readq(addr)		readq((void *)addr)
>>  #endif
>>
> 
> 


-- 
~Randy

^ permalink raw reply

* Re: [PATCH] net/mlx5e: Allow removing representors netdev to other namespace
From: Tonghao Zhang @ 2019-08-01  0:44 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: Roi Dayan, Saeed Mahameed, Linux Netdev List
In-Reply-To: <CAJ3xEMj43wFacxR1bfqG8B0yVPiPyCh=DT5S3TojV8S8ZHaDsA@mail.gmail.com>

On Wed, May 22, 2019 at 12:49 PM Or Gerlitz <gerlitz.or@gmail.com> wrote:
>
> On Wed, May 22, 2019 at 4:26 AM Tonghao Zhang <xiangxia.m.yue@gmail.com> wrote:
>
> > I review the reps of netronome nfp codes,  nfp does't set the
> > NETIF_F_NETNS_LOCAL to netdev->features.
> > And I changed the OFED codes which used for our product environment,
> > and then send this patch to upstream.
>
> The real question here is if we can provide the required separation when
> vport rep netdevs are put into different name-spaces -- this needs deeper
> thinking. Technically you can do that with this one liner patch but we have
> to see if/what assumptions could be broken as of that.
Hi Or,
Can we add a mode parm for allowing user to switch it off/on ?

^ permalink raw reply

* [RFC iproute2 0/4] Revert tc batchsize feature
From: Stephen Hemminger @ 2019-08-01  0:45 UTC (permalink / raw)
  To: jiri, chrism; +Cc: netdev, Stephen Hemminger

The batchsize feature of tc might save a few cycles but it
is a maintaince nightmare, it has uninitialized variables and
poor error handling. 

This patch set reverts back to the original state.
Please don't resubmit original code. Go back to the drawing
board and do something generic.  For example, the routing
daemons have figured out that by using multiple threads and
turning off the netlink ACK they can update millions of routes
quickly.

Stephen Hemminger (4):
  Revert "tc: Remove pointless assignments in batch()"
  Revert "tc: flush after each command in batch mode"
  Revert "tc: fix batch force option"
  Revert "tc: Add batchsize feature for filter and actions"

 tc/m_action.c  |  65 ++++++----------
 tc/tc.c        | 201 ++++---------------------------------------------
 tc/tc_common.h |   7 +-
 tc/tc_filter.c | 129 ++++++++++++-------------------
 4 files changed, 87 insertions(+), 315 deletions(-)


^ permalink raw reply

* [RFC iproute2 1/4] Revert "tc: Remove pointless assignments in batch()"
From: Stephen Hemminger @ 2019-08-01  0:45 UTC (permalink / raw)
  To: jiri, chrism; +Cc: netdev, Stephen Hemminger
In-Reply-To: <20190801004506.9049-1-stephen@networkplumber.org>

This reverts commit 6358bbc381c6e38465838370bcbbdeb77ec3565a.
---
 tc/tc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tc/tc.c b/tc/tc.c
index 64e342dd85bf..1f23971ae4b9 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -326,11 +326,11 @@ static int batch(const char *name)
 	struct batch_buf *head = NULL, *tail = NULL, *buf_pool = NULL;
 	char *largv[100], *largv_next[100];
 	char *line, *line_next = NULL;
+	bool bs_enabled_next = false;
 	bool bs_enabled = false;
 	bool lastline = false;
 	int largc, largc_next;
 	bool bs_enabled_saved;
-	bool bs_enabled_next;
 	int batchsize = 0;
 	size_t len = 0;
 	int ret = 0;
@@ -359,6 +359,7 @@ static int batch(const char *name)
 		goto Exit;
 	largc = makeargs(line, largv, 100);
 	bs_enabled = batchsize_enabled(largc, largv);
+	bs_enabled_saved = bs_enabled;
 	do {
 		if (getcmdline(&line_next, &len, stdin) == -1)
 			lastline = true;
@@ -394,6 +395,7 @@ static int batch(const char *name)
 		len = 0;
 		bs_enabled_saved = bs_enabled;
 		bs_enabled = bs_enabled_next;
+		bs_enabled_next = false;
 
 		if (largc == 0) {
 			largc = largc_next;
-- 
2.20.1


^ permalink raw reply related

* [RFC iproute2 3/4] Revert "tc: fix batch force option"
From: Stephen Hemminger @ 2019-08-01  0:45 UTC (permalink / raw)
  To: jiri, chrism; +Cc: netdev, Stephen Hemminger
In-Reply-To: <20190801004506.9049-1-stephen@networkplumber.org>

This reverts commit b133392468d1f404077a8f3554d1f63d48bb45e8.
---
 tc/tc.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/tc/tc.c b/tc/tc.c
index c115155b2234..b7b6bd288897 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -334,7 +334,6 @@ static int batch(const char *name)
 	int batchsize = 0;
 	size_t len = 0;
 	int ret = 0;
-	int err;
 	bool send;
 
 	batch_mode = 1;
@@ -403,9 +402,9 @@ static int batch(const char *name)
 			continue;	/* blank line */
 		}
 
-		err = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
+		ret = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
 			     tail == NULL ? 0 : sizeof(tail->buf));
-		if (err != 0) {
+		if (ret != 0) {
 			fprintf(stderr, "Command failed %s:%d\n", name,
 				cmdlineno - 1);
 			ret = 1;
@@ -427,17 +426,15 @@ static int batch(const char *name)
 				iov->iov_len = n->nlmsg_len;
 			}
 
-			err = rtnl_talk_iov(&rth, iovs, batchsize, NULL);
-			put_batch_bufs(&buf_pool, &head, &tail);
-			free(iovs);
-			if (err < 0) {
+			ret = rtnl_talk_iov(&rth, iovs, batchsize, NULL);
+			if (ret < 0) {
 				fprintf(stderr, "Command failed %s:%d\n", name,
-					cmdlineno - (batchsize + err) - 1);
-				ret = 1;
-				if (!force)
-					break;
+					cmdlineno - (batchsize + ret) - 1);
+				return 2;
 			}
+			put_batch_bufs(&buf_pool, &head, &tail);
 			batchsize = 0;
+			free(iovs);
 		}
 	} while (!lastline);
 
-- 
2.20.1


^ permalink raw reply related

* [RFC iproute2 2/4] Revert "tc: flush after each command in batch mode"
From: Stephen Hemminger @ 2019-08-01  0:45 UTC (permalink / raw)
  To: jiri, chrism; +Cc: netdev, Stephen Hemminger
In-Reply-To: <20190801004506.9049-1-stephen@networkplumber.org>

This reverts commit d66fdfda71e4a30c1ca0ddb7b1a048bef30fe79e.
---
 tc/tc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tc/tc.c b/tc/tc.c
index 1f23971ae4b9..c115155b2234 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -405,7 +405,6 @@ static int batch(const char *name)
 
 		err = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
 			     tail == NULL ? 0 : sizeof(tail->buf));
-		fflush(stdout);
 		if (err != 0) {
 			fprintf(stderr, "Command failed %s:%d\n", name,
 				cmdlineno - 1);
-- 
2.20.1


^ permalink raw reply related

* [RFC iproute2 4/4] Revert "tc: Add batchsize feature for filter and actions"
From: Stephen Hemminger @ 2019-08-01  0:45 UTC (permalink / raw)
  To: jiri, chrism; +Cc: netdev, Stephen Hemminger
In-Reply-To: <20190801004506.9049-1-stephen@networkplumber.org>

This reverts commit 485d0c6001c4aa134b99c86913d6a7089b7b2ab0.
---
 tc/m_action.c  |  65 ++++++----------
 tc/tc.c        | 199 ++++---------------------------------------------
 tc/tc_common.h |   7 +-
 tc/tc_filter.c | 129 ++++++++++++--------------------
 4 files changed, 87 insertions(+), 313 deletions(-)

diff --git a/tc/m_action.c b/tc/m_action.c
index ab6bc0ad28ff..bdc62720879c 100644
--- a/tc/m_action.c
+++ b/tc/m_action.c
@@ -556,61 +556,40 @@ bad_val:
 	return ret;
 }
 
-struct tc_action_req {
-	struct nlmsghdr		n;
-	struct tcamsg		t;
-	char			buf[MAX_MSG];
-};
-
 static int tc_action_modify(int cmd, unsigned int flags,
-			    int *argc_p, char ***argv_p,
-			    void *buf, size_t buflen)
+			    int *argc_p, char ***argv_p)
 {
-	struct tc_action_req *req, action_req;
-	char **argv = *argv_p;
-	struct rtattr *tail;
 	int argc = *argc_p;
-	struct iovec iov;
+	char **argv = *argv_p;
 	int ret = 0;
-
-	if (buf) {
-		req = buf;
-		if (buflen < sizeof (struct tc_action_req)) {
-			fprintf(stderr, "buffer is too small: %zu\n", buflen);
-			return -1;
-		}
-	} else {
-		memset(&action_req, 0, sizeof (struct tc_action_req));
-		req = &action_req;
-	}
-
-	req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg));
-	req->n.nlmsg_flags = NLM_F_REQUEST | flags;
-	req->n.nlmsg_type = cmd;
-	req->t.tca_family = AF_UNSPEC;
-	tail = NLMSG_TAIL(&req->n);
+	struct {
+		struct nlmsghdr         n;
+		struct tcamsg           t;
+		char                    buf[MAX_MSG];
+	} req = {
+		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)),
+		.n.nlmsg_flags = NLM_F_REQUEST | flags,
+		.n.nlmsg_type = cmd,
+		.t.tca_family = AF_UNSPEC,
+	};
+	struct rtattr *tail = NLMSG_TAIL(&req.n);
 
 	argc -= 1;
 	argv += 1;
-	if (parse_action(&argc, &argv, TCA_ACT_TAB, &req->n)) {
+	if (parse_action(&argc, &argv, TCA_ACT_TAB, &req.n)) {
 		fprintf(stderr, "Illegal \"action\"\n");
 		return -1;
 	}
-	tail->rta_len = (void *) NLMSG_TAIL(&req->n) - (void *) tail;
+	tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
 
-	*argc_p = argc;
-	*argv_p = argv;
-
-	if (buf)
-		return 0;
-
-	iov.iov_base = &req->n;
-	iov.iov_len = req->n.nlmsg_len;
-	if (rtnl_talk_iov(&rth, &iov, 1, NULL) < 0) {
+	if (rtnl_talk(&rth, &req.n, NULL) < 0) {
 		fprintf(stderr, "We have an error talking to the kernel\n");
 		ret = -1;
 	}
 
+	*argc_p = argc;
+	*argv_p = argv;
+
 	return ret;
 }
 
@@ -711,7 +690,7 @@ bad_val:
 	return ret;
 }
 
-int do_action(int argc, char **argv, void *buf, size_t buflen)
+int do_action(int argc, char **argv)
 {
 
 	int ret = 0;
@@ -721,12 +700,12 @@ int do_action(int argc, char **argv, void *buf, size_t buflen)
 		if (matches(*argv, "add") == 0) {
 			ret =  tc_action_modify(RTM_NEWACTION,
 						NLM_F_EXCL | NLM_F_CREATE,
-						&argc, &argv, buf, buflen);
+						&argc, &argv);
 		} else if (matches(*argv, "change") == 0 ||
 			  matches(*argv, "replace") == 0) {
 			ret = tc_action_modify(RTM_NEWACTION,
 					       NLM_F_CREATE | NLM_F_REPLACE,
-					       &argc, &argv, buf, buflen);
+					       &argc, &argv);
 		} else if (matches(*argv, "delete") == 0) {
 			argc -= 1;
 			argv += 1;
diff --git a/tc/tc.c b/tc/tc.c
index b7b6bd288897..a0a18f380b46 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -205,18 +205,18 @@ static void usage(void)
 		"		     -nm | -nam[es] | { -cf | -conf } path }\n");
 }
 
-static int do_cmd(int argc, char **argv, void *buf, size_t buflen)
+static int do_cmd(int argc, char **argv)
 {
 	if (matches(*argv, "qdisc") == 0)
 		return do_qdisc(argc-1, argv+1);
 	if (matches(*argv, "class") == 0)
 		return do_class(argc-1, argv+1);
 	if (matches(*argv, "filter") == 0)
-		return do_filter(argc-1, argv+1, buf, buflen);
+		return do_filter(argc-1, argv+1);
 	if (matches(*argv, "chain") == 0)
-		return do_chain(argc-1, argv+1, buf, buflen);
+		return do_chain(argc-1, argv+1);
 	if (matches(*argv, "actions") == 0)
-		return do_action(argc-1, argv+1, buf, buflen);
+		return do_action(argc-1, argv+1);
 	if (matches(*argv, "monitor") == 0)
 		return do_tcmonitor(argc-1, argv+1);
 	if (matches(*argv, "exec") == 0)
@@ -231,110 +231,11 @@ static int do_cmd(int argc, char **argv, void *buf, size_t buflen)
 	return -1;
 }
 
-#define TC_MAX_SUBC	10
-static bool batchsize_enabled(int argc, char *argv[])
-{
-	struct {
-		char *c;
-		char *subc[TC_MAX_SUBC];
-	} table[] = {
-		{ "filter", { "add", "delete", "change", "replace", NULL} },
-		{ "actions", { "add", "change", "replace", NULL} },
-		{ NULL },
-	}, *iter;
-	char *s;
-	int i;
-
-	if (argc < 2)
-		return false;
-
-	for (iter = table; iter->c; iter++) {
-		if (matches(argv[0], iter->c))
-			continue;
-		for (i = 0; i < TC_MAX_SUBC; i++) {
-			s = iter->subc[i];
-			if (s && matches(argv[1], s) == 0)
-				return true;
-		}
-	}
-
-	return false;
-}
-
-struct batch_buf {
-	struct batch_buf	*next;
-	char			buf[16420];	/* sizeof (struct nlmsghdr) +
-						   max(sizeof (struct tcmsg) +
-						   sizeof (struct tcamsg)) +
-						   MAX_MSG */
-};
-
-static struct batch_buf *get_batch_buf(struct batch_buf **pool,
-				       struct batch_buf **head,
-				       struct batch_buf **tail)
-{
-	struct batch_buf *buf;
-
-	if (*pool == NULL)
-		buf = calloc(1, sizeof(struct batch_buf));
-	else {
-		buf = *pool;
-		*pool = (*pool)->next;
-		memset(buf, 0, sizeof(struct batch_buf));
-	}
-
-	if (*head == NULL)
-		*head = *tail = buf;
-	else {
-		(*tail)->next = buf;
-		(*tail) = buf;
-	}
-
-	return buf;
-}
-
-static void put_batch_bufs(struct batch_buf **pool,
-			   struct batch_buf **head,
-			   struct batch_buf **tail)
-{
-	if (*head == NULL || *tail == NULL)
-		return;
-
-	if (*pool == NULL)
-		*pool = *head;
-	else {
-		(*tail)->next = *pool;
-		*pool = *head;
-	}
-	*head = NULL;
-	*tail = NULL;
-}
-
-static void free_batch_bufs(struct batch_buf **pool)
-{
-	struct batch_buf *buf;
-
-	for (buf = *pool; buf != NULL; buf = *pool) {
-		*pool = buf->next;
-		free(buf);
-	}
-	*pool = NULL;
-}
-
 static int batch(const char *name)
 {
-	struct batch_buf *head = NULL, *tail = NULL, *buf_pool = NULL;
-	char *largv[100], *largv_next[100];
-	char *line, *line_next = NULL;
-	bool bs_enabled_next = false;
-	bool bs_enabled = false;
-	bool lastline = false;
-	int largc, largc_next;
-	bool bs_enabled_saved;
-	int batchsize = 0;
+	char *line = NULL;
 	size_t len = 0;
 	int ret = 0;
-	bool send;
 
 	batch_mode = 1;
 	if (name && strcmp(name, "-") != 0) {
@@ -354,95 +255,25 @@ static int batch(const char *name)
 	}
 
 	cmdlineno = 0;
-	if (getcmdline(&line, &len, stdin) == -1)
-		goto Exit;
-	largc = makeargs(line, largv, 100);
-	bs_enabled = batchsize_enabled(largc, largv);
-	bs_enabled_saved = bs_enabled;
-	do {
-		if (getcmdline(&line_next, &len, stdin) == -1)
-			lastline = true;
-
-		largc_next = makeargs(line_next, largv_next, 100);
-		bs_enabled_next = batchsize_enabled(largc_next, largv_next);
-		if (bs_enabled) {
-			struct batch_buf *buf;
-
-			buf = get_batch_buf(&buf_pool, &head, &tail);
-			if (!buf) {
-				fprintf(stderr,
-					"failed to allocate batch_buf\n");
-				return -1;
-			}
-			++batchsize;
-		}
+	while (getcmdline(&line, &len, stdin) != -1) {
+		char *largv[100];
+		int largc;
 
-		/*
-		 * In batch mode, if we haven't accumulated enough commands
-		 * and this is not the last command and this command & next
-		 * command both support the batchsize feature, don't send the
-		 * message immediately.
-		 */
-		if (!lastline && bs_enabled && bs_enabled_next
-		    && batchsize != MSG_IOV_MAX)
-			send = false;
-		else
-			send = true;
-
-		line = line_next;
-		line_next = NULL;
-		len = 0;
-		bs_enabled_saved = bs_enabled;
-		bs_enabled = bs_enabled_next;
-		bs_enabled_next = false;
-
-		if (largc == 0) {
-			largc = largc_next;
-			memcpy(largv, largv_next, largc * sizeof(char *));
+		largc = makeargs(line, largv, 100);
+		if (largc == 0)
 			continue;	/* blank line */
-		}
 
-		ret = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
-			     tail == NULL ? 0 : sizeof(tail->buf));
-		if (ret != 0) {
-			fprintf(stderr, "Command failed %s:%d\n", name,
-				cmdlineno - 1);
+		if (do_cmd(largc, largv)) {
+			fprintf(stderr, "Command failed %s:%d\n",
+				name, cmdlineno);
 			ret = 1;
 			if (!force)
 				break;
 		}
-		largc = largc_next;
-		memcpy(largv, largv_next, largc * sizeof(char *));
-
-		if (send && bs_enabled_saved) {
-			struct iovec *iov, *iovs;
-			struct batch_buf *buf;
-			struct nlmsghdr *n;
-
-			iov = iovs = malloc(batchsize * sizeof(struct iovec));
-			for (buf = head; buf != NULL; buf = buf->next, ++iov) {
-				n = (struct nlmsghdr *)&buf->buf;
-				iov->iov_base = n;
-				iov->iov_len = n->nlmsg_len;
-			}
-
-			ret = rtnl_talk_iov(&rth, iovs, batchsize, NULL);
-			if (ret < 0) {
-				fprintf(stderr, "Command failed %s:%d\n", name,
-					cmdlineno - (batchsize + ret) - 1);
-				return 2;
-			}
-			put_batch_bufs(&buf_pool, &head, &tail);
-			batchsize = 0;
-			free(iovs);
-		}
-	} while (!lastline);
+	}
 
-	free_batch_bufs(&buf_pool);
-Exit:
 	free(line);
 	rtnl_close(&rth);
-
 	return ret;
 }
 
@@ -536,7 +367,7 @@ int main(int argc, char **argv)
 		goto Exit;
 	}
 
-	ret = do_cmd(argc-1, argv+1, NULL, 0);
+	ret = do_cmd(argc-1, argv+1);
 Exit:
 	rtnl_close(&rth);
 
diff --git a/tc/tc_common.h b/tc/tc_common.h
index d8a6dfdeabd4..802fb7f01fe4 100644
--- a/tc/tc_common.h
+++ b/tc/tc_common.h
@@ -1,15 +1,14 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
 #define TCA_BUF_MAX	(64*1024)
-#define MSG_IOV_MAX	128
 
 extern struct rtnl_handle rth;
 
 int do_qdisc(int argc, char **argv);
 int do_class(int argc, char **argv);
-int do_filter(int argc, char **argv, void *buf, size_t buflen);
-int do_chain(int argc, char **argv, void *buf, size_t buflen);
-int do_action(int argc, char **argv, void *buf, size_t buflen);
+int do_filter(int argc, char **argv);
+int do_chain(int argc, char **argv);
+int do_action(int argc, char **argv);
 int do_tcmonitor(int argc, char **argv);
 int do_exec(int argc, char **argv);
 
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index cd78c2441efa..53759a7a8876 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -58,42 +58,30 @@ struct tc_filter_req {
 	char			buf[MAX_MSG];
 };
 
-static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv,
-			    void *buf, size_t buflen)
+static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
 {
-	struct tc_filter_req *req, filter_req;
+	struct {
+		struct nlmsghdr	n;
+		struct tcmsg		t;
+		char			buf[MAX_MSG];
+	} req = {
+		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
+		.n.nlmsg_flags = NLM_F_REQUEST | flags,
+		.n.nlmsg_type = cmd,
+		.t.tcm_family = AF_UNSPEC,
+	};
 	struct filter_util *q = NULL;
-	struct tc_estimator est = {};
-	char k[FILTER_NAMESZ] = {};
-	int chain_index_set = 0;
-	char d[IFNAMSIZ] = {};
-	int protocol_set = 0;
-	__u32 block_index = 0;
-	char *fhandle = NULL;
+	__u32 prio = 0;
 	__u32 protocol = 0;
+	int protocol_set = 0;
 	__u32 chain_index;
-	struct iovec iov;
-	__u32 prio = 0;
-	int ret;
-
-	if (buf) {
-		req = buf;
-		if (buflen < sizeof (struct tc_filter_req)) {
-			fprintf(stderr, "buffer is too small: %zu\n", buflen);
-			return -1;
-		}
-	} else {
-		memset(&filter_req, 0, sizeof (struct tc_filter_req));
-		req = &filter_req;
-	}
-
-	req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
-	req->n.nlmsg_flags = NLM_F_REQUEST | flags;
-	req->n.nlmsg_type = cmd;
-	req->t.tcm_family = AF_UNSPEC;
+	int chain_index_set = 0;
+	char *fhandle = NULL;
+	char  d[IFNAMSIZ] = {};
+	char  k[FILTER_NAMESZ] = {};
+	struct tc_estimator est = {};
 
-	if ((cmd == RTM_NEWTFILTER || cmd == RTM_NEWCHAIN) &&
-	    flags & NLM_F_CREATE)
+	if (cmd == RTM_NEWTFILTER && flags & NLM_F_CREATE)
 		protocol = htons(ETH_P_ALL);
 
 	while (argc > 0) {
@@ -101,53 +89,39 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv,
 			NEXT_ARG();
 			if (d[0])
 				duparg("dev", *argv);
-			if (block_index) {
-				fprintf(stderr, "Error: \"dev\" and \"block\" are mutually exlusive\n");
-				return -1;
-			}
 			strncpy(d, *argv, sizeof(d)-1);
-		} else if (matches(*argv, "block") == 0) {
-			NEXT_ARG();
-			if (block_index)
-				duparg("block", *argv);
-			if (d[0]) {
-				fprintf(stderr, "Error: \"dev\" and \"block\" are mutually exlusive\n");
-				return -1;
-			}
-			if (get_u32(&block_index, *argv, 0) || !block_index)
-				invarg("invalid block index value", *argv);
 		} else if (strcmp(*argv, "root") == 0) {
-			if (req->t.tcm_parent) {
+			if (req.t.tcm_parent) {
 				fprintf(stderr,
 					"Error: \"root\" is duplicate parent ID\n");
 				return -1;
 			}
-			req->t.tcm_parent = TC_H_ROOT;
+			req.t.tcm_parent = TC_H_ROOT;
 		} else if (strcmp(*argv, "ingress") == 0) {
-			if (req->t.tcm_parent) {
+			if (req.t.tcm_parent) {
 				fprintf(stderr,
 					"Error: \"ingress\" is duplicate parent ID\n");
 				return -1;
 			}
-			req->t.tcm_parent = TC_H_MAKE(TC_H_CLSACT,
+			req.t.tcm_parent = TC_H_MAKE(TC_H_CLSACT,
 						     TC_H_MIN_INGRESS);
 		} else if (strcmp(*argv, "egress") == 0) {
-			if (req->t.tcm_parent) {
+			if (req.t.tcm_parent) {
 				fprintf(stderr,
 					"Error: \"egress\" is duplicate parent ID\n");
 				return -1;
 			}
-			req->t.tcm_parent = TC_H_MAKE(TC_H_CLSACT,
+			req.t.tcm_parent = TC_H_MAKE(TC_H_CLSACT,
 						     TC_H_MIN_EGRESS);
 		} else if (strcmp(*argv, "parent") == 0) {
 			__u32 handle;
 
 			NEXT_ARG();
-			if (req->t.tcm_parent)
+			if (req.t.tcm_parent)
 				duparg("parent", *argv);
 			if (get_tc_classid(&handle, *argv))
 				invarg("Invalid parent ID", *argv);
-			req->t.tcm_parent = handle;
+			req.t.tcm_parent = handle;
 		} else if (strcmp(*argv, "handle") == 0) {
 			NEXT_ARG();
 			if (fhandle)
@@ -194,27 +168,26 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv,
 		argc--; argv++;
 	}
 
-	req->t.tcm_info = TC_H_MAKE(prio<<16, protocol);
+	req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
 
 	if (chain_index_set)
-		addattr32(&req->n, sizeof(*req), TCA_CHAIN, chain_index);
+		addattr32(&req.n, sizeof(req), TCA_CHAIN, chain_index);
 
 	if (k[0])
-		addattr_l(&req->n, sizeof(*req), TCA_KIND, k, strlen(k)+1);
+		addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
 
 	if (d[0])  {
 		ll_init_map(&rth);
 
-		req->t.tcm_ifindex = ll_name_to_index(d);
-		if (!req->t.tcm_ifindex)
-			return -nodev(d);
-	} else if (block_index) {
-		req->t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
-		req->t.tcm_block_index = block_index;
+		req.t.tcm_ifindex = ll_name_to_index(d);
+		if (req.t.tcm_ifindex == 0) {
+			fprintf(stderr, "Cannot find device \"%s\"\n", d);
+			return 1;
+		}
 	}
 
 	if (q) {
-		if (q->parse_fopt(q, fhandle, argc, argv, &req->n))
+		if (q->parse_fopt(q, fhandle, argc, argv, &req.n))
 			return 1;
 	} else {
 		if (fhandle) {
@@ -233,16 +206,10 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv,
 	}
 
 	if (est.ewma_log)
-		addattr_l(&req->n, sizeof(*req), TCA_RATE, &est, sizeof(est));
+		addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est));
 
-	if (buf)
-		return 0;
-
-	iov.iov_base = &req->n;
-	iov.iov_len = req->n.nlmsg_len;
-	ret = rtnl_talk_iov(&rth, &iov, 1, NULL);
-	if (ret < 0) {
-		fprintf(stderr, "We have an error talking to the kernel, %d\n", ret);
+	if (rtnl_talk(&rth, &req.n, NULL) < 0) {
+		fprintf(stderr, "We have an error talking to the kernel\n");
 		return 2;
 	}
 
@@ -751,22 +718,20 @@ static int tc_filter_list(int cmd, int argc, char **argv)
 	return 0;
 }
 
-int do_filter(int argc, char **argv, void *buf, size_t buflen)
+int do_filter(int argc, char **argv)
 {
 	if (argc < 1)
 		return tc_filter_list(RTM_GETTFILTER, 0, NULL);
 	if (matches(*argv, "add") == 0)
 		return tc_filter_modify(RTM_NEWTFILTER, NLM_F_EXCL|NLM_F_CREATE,
-					argc-1, argv+1, buf, buflen);
+					argc-1, argv+1);
 	if (matches(*argv, "change") == 0)
-		return tc_filter_modify(RTM_NEWTFILTER, 0, argc-1, argv+1,
-					buf, buflen);
+		return tc_filter_modify(RTM_NEWTFILTER, 0, argc-1, argv+1);
 	if (matches(*argv, "replace") == 0)
 		return tc_filter_modify(RTM_NEWTFILTER, NLM_F_CREATE, argc-1,
-					argv+1, buf, buflen);
+					argv+1);
 	if (matches(*argv, "delete") == 0)
-		return tc_filter_modify(RTM_DELTFILTER, 0, argc-1, argv+1,
-					buf, buflen);
+		return tc_filter_modify(RTM_DELTFILTER, 0,  argc-1, argv+1);
 	if (matches(*argv, "get") == 0)
 		return tc_filter_get(RTM_GETTFILTER, 0,  argc-1, argv+1);
 	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
@@ -781,16 +746,16 @@ int do_filter(int argc, char **argv, void *buf, size_t buflen)
 	return -1;
 }
 
-int do_chain(int argc, char **argv, void *buf, size_t buflen)
+int do_chain(int argc, char **argv)
 {
 	if (argc < 1)
 		return tc_filter_list(RTM_GETCHAIN, 0, NULL);
 	if (matches(*argv, "add") == 0) {
 		return tc_filter_modify(RTM_NEWCHAIN, NLM_F_EXCL | NLM_F_CREATE,
-					argc - 1, argv + 1, buf, buflen);
+					argc - 1, argv + 1);
 	} else if (matches(*argv, "delete") == 0) {
 		return tc_filter_modify(RTM_DELCHAIN, 0,
-					argc - 1, argv + 1, buf, buflen);
+					argc - 1, argv + 1);
 	} else if (matches(*argv, "get") == 0) {
 		return tc_filter_get(RTM_GETCHAIN, 0,
 				     argc - 1, argv + 1);
-- 
2.20.1


^ permalink raw reply related

* RE: [PATCH v2 net] hv_sock: Fix hang when a connection is closed
From: Sunil Muthuswamy @ 2019-08-01  0:50 UTC (permalink / raw)
  To: Dexuan Cui, David Miller, netdev@vger.kernel.org
  Cc: KY Srinivasan, Haiyang Zhang, Stephen Hemminger,
	sashal@kernel.org, Michael Kelley, linux-hyperv@vger.kernel.org,
	linux-kernel@vger.kernel.org, olaf@aepfle.de, apw@canonical.com,
	jasowang@redhat.com, vkuznets, marcelo.cerri@canonical.com
In-Reply-To: <PU1P153MB01696DDD3A3F601370701DD2BFDF0@PU1P153MB0169.APCP153.PROD.OUTLOOK.COM>

> -----Original Message-----
> From: Dexuan Cui <decui@microsoft.com>
> Sent: Tuesday, July 30, 2019 6:26 PM
> To: Sunil Muthuswamy <sunilmut@microsoft.com>; David Miller <davem@davemloft.net>; netdev@vger.kernel.org
> Cc: KY Srinivasan <kys@microsoft.com>; Haiyang Zhang <haiyangz@microsoft.com>; Stephen Hemminger
> <sthemmin@microsoft.com>; sashal@kernel.org; Michael Kelley <mikelley@microsoft.com>; linux-hyperv@vger.kernel.org; linux-
> kernel@vger.kernel.org; olaf@aepfle.de; apw@canonical.com; jasowang@redhat.com; vkuznets <vkuznets@redhat.com>;
> marcelo.cerri@canonical.com
> Subject: [PATCH v2 net] hv_sock: Fix hang when a connection is closed
> 
> 
> There is a race condition for an established connection that is being closed
> by the guest: the refcnt is 4 at the end of hvs_release() (Note: here the
> 'remove_sock' is false):
> 
> 1 for the initial value;
> 1 for the sk being in the bound list;
> 1 for the sk being in the connected list;
> 1 for the delayed close_work.
> 
> After hvs_release() finishes, __vsock_release() -> sock_put(sk) *may*
> decrease the refcnt to 3.
> 
> Concurrently, hvs_close_connection() runs in another thread:
>   calls vsock_remove_sock() to decrease the refcnt by 2;
>   call sock_put() to decrease the refcnt to 0, and free the sk;
>   next, the "release_sock(sk)" may hang due to use-after-free.
> 
> In the above, after hvs_release() finishes, if hvs_close_connection() runs
> faster than "__vsock_release() -> sock_put(sk)", then there is not any issue,
> because at the beginning of hvs_close_connection(), the refcnt is still 4.
> 
> The issue can be resolved if an extra reference is taken when the
> connection is established.
> 
> Fixes: a9eeb998c28d ("hv_sock: Add support for delayed close")
> Signed-off-by: Dexuan Cui <decui@microsoft.com>
> Cc: stable@vger.kernel.org
> 
> ---
> 
> Changes in v2:
>   Changed the location of the sock_hold() call.
>   Updated the changelog accordingly.
> 
>   Thanks Sunil for the suggestion!
> 
> 
> With the proper kernel debugging options enabled, first a warning can
> appear:
> 
> kworker/1:0/4467 is freeing memory ..., with a lock still held there!
> stack backtrace:
> Workqueue: events vmbus_onmessage_work [hv_vmbus]
> Call Trace:
>  dump_stack+0x67/0x90
>  debug_check_no_locks_freed.cold.52+0x78/0x7d
>  slab_free_freelist_hook+0x85/0x140
>  kmem_cache_free+0xa5/0x380
>  __sk_destruct+0x150/0x260
>  hvs_close_connection+0x24/0x30 [hv_sock]
>  vmbus_onmessage_work+0x1d/0x30 [hv_vmbus]
>  process_one_work+0x241/0x600
>  worker_thread+0x3c/0x390
>  kthread+0x11b/0x140
>  ret_from_fork+0x24/0x30
> 
> and then the following release_sock(sk) can hang:
> 
> watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [kworker/1:0:4467]
> ...
> irq event stamp: 62890
> CPU: 1 PID: 4467 Comm: kworker/1:0 Tainted: G        W         5.2.0+ #39
> Workqueue: events vmbus_onmessage_work [hv_vmbus]
> RIP: 0010:queued_spin_lock_slowpath+0x2b/0x1e0
> ...
> Call Trace:
>  do_raw_spin_lock+0xab/0xb0
>  release_sock+0x19/0xb0
>  vmbus_onmessage_work+0x1d/0x30 [hv_vmbus]
>  process_one_work+0x241/0x600
>  worker_thread+0x3c/0x390
>  kthread+0x11b/0x140
>  ret_from_fork+0x24/0x30
> 
>  net/vmw_vsock/hyperv_transport.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
> index f2084e3f7aa4..9d864ebeb7b3 100644
> --- a/net/vmw_vsock/hyperv_transport.c
> +++ b/net/vmw_vsock/hyperv_transport.c
> @@ -312,6 +312,11 @@ static void hvs_close_connection(struct vmbus_channel *chan)
>  	lock_sock(sk);
>  	hvs_do_close_lock_held(vsock_sk(sk), true);
>  	release_sock(sk);
> +
> +	/* Release the refcnt for the channel that's opened in
> +	 * hvs_open_connection().
> +	 */
> +	sock_put(sk);
>  }
> 
>  static void hvs_open_connection(struct vmbus_channel *chan)
> @@ -407,6 +412,9 @@ static void hvs_open_connection(struct vmbus_channel *chan)
>  	}
> 
>  	set_per_channel_state(chan, conn_from_host ? new : sk);
> +
> +	/* This reference will be dropped by hvs_close_connection(). */
> +	sock_hold(conn_from_host ? new : sk);
>  	vmbus_set_chn_rescind_callback(chan, hvs_close_connection);
> 
>  	/* Set the pending send size to max packet size to always get
> --
> 2.19.1

Reviewed-by: Sunil Muthuswamy <sunilmut@microsoft.com>

^ 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