Netdev List
 help / color / mirror / Atom feed
* Re: [REGRESSION][4.13.y][4.14.y][v4.15.y] net: reduce skb_warn_bad_offload() noise
From: Greg Kroah-Hartman @ 2017-12-11 21:44 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: Joseph Salisbury, Eric Dumazet, Dmitry Vyukov, Willem de Bruijn,
	David Miller, Daniel Borkmann, jakub.kicinski, linux,
	John Fastabend, me, idosch, Network Development, LKML, stable,
	1715609
In-Reply-To: <CAF=yD-L_S312Ryyg5fE3p6kqFus4SKQcgL2zXKiofq-ohiK7bg@mail.gmail.com>

On Mon, Dec 11, 2017 at 04:25:26PM -0500, Willem de Bruijn wrote:
> Note that UFO was removed in 4.14 and that skb_warn_bad_offload
> can happen for various types of packets, so there may be multiple
> independent bug reports. I'm investigating two other non-UFO reports
> just now.

Meta-comment, now that UFO is gone from mainline, I'm wondering if I
should just delete it from 4.4 and 4.9 as well.  Any objections for
that?  I'd like to make it easy to maintain these kernels for a while,
and having them diverge like this, with all of the issues around UFO,
seems like it will just make life harder for myself if I leave it in.

Any opinions?

thanks,

greg k-h

^ permalink raw reply

* Re: Huge memory leak with 4.15.0-rc2+
From: Paweł Staszewski @ 2017-12-11 21:48 UTC (permalink / raw)
  To: Linux Kernel Network Developers
In-Reply-To: <c3244df1-464d-0705-f798-896eaffe4c91@itcare.pl>



W dniu 2017-12-11 o 22:23, Paweł Staszewski pisze:
> Hi
>
>
> I just upgraded some testing host to 4.15.0-rc2+ kernel
>
> And after some time of traffic processing - when traffic on all ports 
> reach about 3Mpps - memleak started.
>
> Graph attached from memory usage: https://ibb.co/idK4zb
>
>
>
> HW config:
>
> Intel E5
>
> 8x Intel 82599 (used ixgbe driver from kernel)
>
> Interfaces with vlans attached
>
> All 8 ethernet ports are in one LAG group configured by team.
>
> With current settings
>
> (this host is acting as a router - and bgpd process is eating same 
> amount of memory from the beginning about 5.2GB)
>
>  cat /proc/meminfo
> MemTotal:       32770588 kB
> MemFree:        11342492 kB
> MemAvailable:   10982752 kB
> Buffers:           84704 kB
> Cached:            83180 kB
> SwapCached:            0 kB
> Active:          5105320 kB
> Inactive:          46252 kB
> Active(anon):    4985448 kB
> Inactive(anon):     1096 kB
> Active(file):     119872 kB
> Inactive(file):    45156 kB
> Unevictable:           0 kB
> Mlocked:               0 kB
> SwapTotal:       4005280 kB
> SwapFree:        4005280 kB
> Dirty:               236 kB
> Writeback:             0 kB
> AnonPages:       4983752 kB
> Mapped:            13556 kB
> Shmem:              2852 kB
> Slab:            1013124 kB
> SReclaimable:      45876 kB
> SUnreclaim:       967248 kB
> KernelStack:        7152 kB
> PageTables:        12164 kB
> NFS_Unstable:          0 kB
> Bounce:                0 kB
> WritebackTmp:          0 kB
> CommitLimit:    20390572 kB
> Committed_AS:     396568 kB
> VmallocTotal:   34359738367 kB
> VmallocUsed:           0 kB
> VmallocChunk:          0 kB
> HardwareCorrupted:     0 kB
> AnonHugePages:         0 kB
> ShmemHugePages:        0 kB
> ShmemPmdMapped:        0 kB
> CmaTotal:              0 kB
> CmaFree:               0 kB
> HugePages_Total:       0
> HugePages_Free:        0
> HugePages_Rsvd:        0
> HugePages_Surp:        0
> Hugepagesize:       2048 kB
> DirectMap4k:     1407572 kB
> DirectMap2M:    20504576 kB
> DirectMap1G:    13631488 kB
>
> ps aux --sort -rss
> USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
> root      6758  1.8 14.9 5044996 4886964 ?     Sl   01:22  23:21 
> /usr/local/sbin/bgpd -d  -u root -g root -I --ignore_warnings
> root      6752  0.0  0.1  86272 61920 ?        Ss   01:22   0:16 
> /usr/local/sbin/zebra -d  -u root -g root -I --ignore_warnings
> root      6766 12.6  0.0  51592 29196 ?        S    01:22 157:48 
> /usr/sbin/snmpd -p /var/run/snmpd.pid -Ln
> root      7494  0.0  0.0 708976  5896 ?        Ssl  01:22   0:09 
> /opt/collectd/sbin/collectd
> root     15531  0.0  0.0  67864  5056 ?        Ss   21:57   0:00 sshd: 
> paol [priv]
> root      4915  0.0  0.0 271912  4904 ?        Ss   01:21   0:25 
> /usr/sbin/syslog-ng --persist-file 
> /var/lib/syslog-ng/syslog-ng.persist --cfgfile 
> /etc/syslog-ng/syslog-ng.conf --pidfile /run/syslog-ng.pid
> root      4278  0.0  0.0  37220  4164 ?        Ss   01:21   0:00 
> /lib/systemd/systemd-udevd --daemon
> root      5147  0.0  0.0  32072  3232 ?        Ss   01:21   0:00 
> /usr/sbin/sshd
> root      5203  0.0  0.0  28876  2436 ?        S    01:21   0:00 teamd 
> -d -f /etc/teamd.conf
> root     17372  0.0  0.0  17924  2388 pts/2    R+   22:13   0:00 ps 
> aux --sort -rss
> root      4789  0.0  0.0   5032  2176 ?        Ss   01:21   0:00 mdadm 
> --monitor --scan --daemonise --pid-file /var/run/mdadm.pid --syslog
> root      7511  0.0  0.0  12676  1920 tty4     Ss+  01:22   0:00 
> /sbin/agetty 38400 tty4 linux
> root      7510  0.0  0.0  12676  1896 tty3     Ss+  01:22   0:00 
> /sbin/agetty 38400 tty3 linux
> root      7512  0.0  0.0  12676  1860 tty5     Ss+  01:22   0:00 
> /sbin/agetty 38400 tty5 linux
> root      7513  0.0  0.0  12676  1836 tty6     Ss+  01:22   0:00 
> /sbin/agetty 38400 tty6 linux
> root      7509  0.0  0.0  12676  1832 tty2     Ss+  01:22   0:00 
> /sbin/agetty 38400 tty2 linux
>
> And latest kernel that everything was working is: 4.14.3
>
>
> Some observations - when i disable tso on all cards there is more 
> memleak.
>
>
>
>
>
When traffic starts to drop - there is less and less memleak
below link to memory usage graph:
https://ibb.co/hU97kG

And there is rising slab_unrecl - Amount of unreclaimable memory used 
for slab kernel allocations


Forgot to add that im using hfsc and qdiscs like pfifo on classes.

^ permalink raw reply

* Re: [PATCH v5] leds: trigger: Introduce a NETDEV trigger
From: Jacek Anaszewski @ 2017-12-11 21:53 UTC (permalink / raw)
  To: Ben Whitten, rpurdie, pavel; +Cc: linux-leds, linux-kernel, netdev
In-Reply-To: <1512940675-9536-1-git-send-email-ben.whitten@gmail.com>

Hi Ben,

Thanks for the update.

On 12/10/2017 10:17 PM, Ben Whitten wrote:
> This commit introduces a NETDEV trigger for named device
> activity. Available triggers are link, rx, and tx.
> 
> Signed-off-by: Ben Whitten <ben.whitten@gmail.com>
> 
> ---
> Changes in v5:
> Adjust header comment style to be consistent
> Changes in v4:
> Adopt SPDX licence header
> Changes in v3:
> Cancel the software blink prior to a oneshot re-queue
> Changes in v2:
> Sort includes and redate documentation
> Correct licence
> Remove macro and replace with generic function using enums
> Convert blink logic in stats work to use led_blink_oneshot
> Uses configured brightness instead of FULL
> ---
>  .../ABI/testing/sysfs-class-led-trigger-netdev     |  45 ++
>  drivers/leds/trigger/Kconfig                       |   7 +
>  drivers/leds/trigger/Makefile                      |   1 +
>  drivers/leds/trigger/ledtrig-netdev.c              | 496 +++++++++++++++++++++
>  4 files changed, 549 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
>  create mode 100644 drivers/leds/trigger/ledtrig-netdev.c
> 
> diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
> new file mode 100644
> index 0000000..451af6d
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
> @@ -0,0 +1,45 @@
> +What:		/sys/class/leds/<led>/device_name
> +Date:		Dec 2017
> +KernelVersion:	4.16
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Specifies the network device name to monitor.
> +
> +What:		/sys/class/leds/<led>/interval
> +Date:		Dec 2017
> +KernelVersion:	4.16
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Specifies the duration of the LED blink in milliseconds.
> +		Defaults to 50 ms.
> +
> +What:		/sys/class/leds/<led>/link
> +Date:		Dec 2017
> +KernelVersion:	4.16
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Signal the link state of the named network device.
> +		If set to 0 (default), the LED's normal state is off.
> +		If set to 1, the LED's normal state reflects the link state
> +		of the named network device.
> +		Setting this value also immediately changes the LED state.
> +
> +What:		/sys/class/leds/<led>/tx
> +Date:		Dec 2017
> +KernelVersion:	4.16
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Signal transmission of data on the named network device.
> +		If set to 0 (default), the LED will not blink on transmission.
> +		If set to 1, the LED will blink for the milliseconds specified
> +		in interval to signal transmission.
> +
> +What:		/sys/class/leds/<led>/rx
> +Date:		Dec 2017
> +KernelVersion:	4.16
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Signal reception of data on the named network device.
> +		If set to 0 (default), the LED will not blink on reception.
> +		If set to 1, the LED will blink for the milliseconds specified
> +		in interval to signal reception.
> diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
> index 3f9ddb9..4ec1853 100644
> --- a/drivers/leds/trigger/Kconfig
> +++ b/drivers/leds/trigger/Kconfig
> @@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
>  	  a different trigger.
>  	  If unsure, say Y.
>  
> +config LEDS_TRIGGER_NETDEV
> +	tristate "LED Netdev Trigger"
> +	depends on NET && LEDS_TRIGGERS
> +	help
> +	  This allows LEDs to be controlled by network device activity.
> +	  If unsure, say Y.
> +
>  endif # LEDS_TRIGGERS
> diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
> index 9f2e868..59e163d 100644
> --- a/drivers/leds/trigger/Makefile
> +++ b/drivers/leds/trigger/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
>  obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)	+= ledtrig-transient.o
>  obj-$(CONFIG_LEDS_TRIGGER_CAMERA)	+= ledtrig-camera.o
>  obj-$(CONFIG_LEDS_TRIGGER_PANIC)	+= ledtrig-panic.o
> +obj-$(CONFIG_LEDS_TRIGGER_NETDEV)	+= ledtrig-netdev.o
> diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
> new file mode 100644
> index 0000000..6df4781
> --- /dev/null
> +++ b/drivers/leds/trigger/ledtrig-netdev.c
> @@ -0,0 +1,496 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright 2017 Ben Whitten <ben.whitten@gmail.com>
> +// Copyright 2007 Oliver Jowett <oliver@opencloud.com>
> +//
> +// LED Kernel Netdev Trigger
> +//
> +// Toggles the LED to reflect the link and traffic state of a named net device
> +//
> +// Derived from ledtrig-timer.c which is:
> +//  Copyright 2005-2006 Openedhand Ltd.
> +//  Author: Richard Purdie <rpurdie@openedhand.com>
> +
> +#include <linux/atomic.h>
> +#include <linux/ctype.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/jiffies.h>
> +#include <linux/kernel.h>
> +#include <linux/leds.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/spinlock.h>
> +#include <linux/timer.h>
> +#include "../leds.h"
> +
> +/*
> + * Configurable sysfs attributes:
> + *
> + * device_name - network device name to monitor
> + * interval - duration of LED blink, in milliseconds
> + * link -  LED's normal state reflects whether the link is up
> + *         (has carrier) or not
> + * tx -  LED blinks on transmitted data
> + * rx -  LED blinks on receive data
> + *
> + */
> +
> +struct led_netdev_data {
> +	spinlock_t lock;
> +
> +	struct delayed_work work;
> +	struct notifier_block notifier;
> +
> +	struct led_classdev *led_cdev;
> +	struct net_device *net_dev;
> +
> +	char device_name[IFNAMSIZ];
> +	atomic_t interval;
> +	unsigned int last_activity;
> +
> +	unsigned long mode;
> +#define NETDEV_LED_LINK	0
> +#define NETDEV_LED_TX	1
> +#define NETDEV_LED_RX	2
> +#define NETDEV_LED_MODE_LINKUP	3
> +};
> +
> +enum netdev_led_attr {
> +	NETDEV_ATTR_LINK,
> +	NETDEV_ATTR_TX,
> +	NETDEV_ATTR_RX
> +};
> +
> +static void set_baseline_state(struct led_netdev_data *trigger_data)
> +{
> +	int current_brightness;
> +	struct led_classdev *led_cdev = trigger_data->led_cdev;
> +
> +	current_brightness = led_cdev->brightness;
> +	if (current_brightness)
> +		led_cdev->blink_brightness = current_brightness;
> +	if (!led_cdev->blink_brightness)
> +		led_cdev->blink_brightness = led_cdev->max_brightness;
> +
> +	if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode))
> +		led_set_brightness(led_cdev, LED_OFF);
> +	else {
> +		if (test_bit(NETDEV_LED_LINK, &trigger_data->mode))
> +			led_set_brightness(led_cdev,
> +					   led_cdev->blink_brightness);
> +		else
> +			led_set_brightness(led_cdev, LED_OFF);
> +
> +		/* If we are looking for RX/TX start periodically
> +		 * checking stats
> +		 */
> +		if (test_bit(NETDEV_LED_TX, &trigger_data->mode) ||
> +		    test_bit(NETDEV_LED_RX, &trigger_data->mode))
> +			schedule_delayed_work(&trigger_data->work, 0);
> +	}
> +}
> +
> +static ssize_t device_name_show(struct device *dev,
> +				struct device_attribute *attr, char *buf)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +	ssize_t len;
> +
> +	spin_lock_bh(&trigger_data->lock);
> +	len = sprintf(buf, "%s\n", trigger_data->device_name);
> +	spin_unlock_bh(&trigger_data->lock);
> +
> +	return len;
> +}
> +
> +static ssize_t device_name_store(struct device *dev,
> +				 struct device_attribute *attr, const char *buf,
> +				 size_t size)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +
> +	if (size >= IFNAMSIZ)
> +		return -EINVAL;
> +
> +	cancel_delayed_work_sync(&trigger_data->work);
> +
> +	spin_lock_bh(&trigger_data->lock);
> +
> +	if (trigger_data->net_dev) {
> +		dev_put(trigger_data->net_dev);
> +		trigger_data->net_dev = NULL;
> +	}
> +
> +	strncpy(trigger_data->device_name, buf, size);
> +	if (size > 0 && trigger_data->device_name[size - 1] == '\n')
> +		trigger_data->device_name[size - 1] = 0;
> +
> +	if (trigger_data->device_name[0] != 0)
> +		trigger_data->net_dev =
> +		    dev_get_by_name(&init_net, trigger_data->device_name);
> +
> +	clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
> +	if (trigger_data->net_dev != NULL)
> +		if (netif_carrier_ok(trigger_data->net_dev))
> +			set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
> +
> +	trigger_data->last_activity = 0;
> +
> +	set_baseline_state(trigger_data);
> +	spin_unlock_bh(&trigger_data->lock);
> +
> +	return size;
> +}
> +
> +static DEVICE_ATTR_RW(device_name);
> +
> +static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
> +	enum netdev_led_attr attr)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +	int bit;
> +
> +	switch (attr) {
> +	case NETDEV_ATTR_LINK:
> +		bit = NETDEV_LED_LINK;
> +		break;
> +	case NETDEV_ATTR_TX:
> +		bit = NETDEV_LED_TX;
> +		break;
> +	case NETDEV_ATTR_RX:
> +		bit = NETDEV_LED_RX;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode));
> +}
> +
> +static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
> +	size_t size, enum netdev_led_attr attr)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +	unsigned long state;
> +	int ret;
> +	int bit;
> +
> +	ret = kstrtoul(buf, 0, &state);
> +	if (ret)
> +		return ret;
> +
> +	switch (attr) {
> +	case NETDEV_ATTR_LINK:
> +		bit = NETDEV_LED_LINK;
> +		break;
> +	case NETDEV_ATTR_TX:
> +		bit = NETDEV_LED_TX;
> +		break;
> +	case NETDEV_ATTR_RX:
> +		bit = NETDEV_LED_RX;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	cancel_delayed_work_sync(&trigger_data->work);
> +
> +	if (state)
> +		set_bit(bit, &trigger_data->mode);
> +	else
> +		clear_bit(bit, &trigger_data->mode);
> +
> +	set_baseline_state(trigger_data);
> +
> +	return size;
> +}
> +
> +static ssize_t link_show(struct device *dev,
> +	struct device_attribute *attr, char *buf)
> +{
> +	return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK);
> +}
> +
> +static ssize_t link_store(struct device *dev,
> +	struct device_attribute *attr, const char *buf, size_t size)
> +{
> +	return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK);
> +}
> +
> +static DEVICE_ATTR_RW(link);
> +
> +static ssize_t tx_show(struct device *dev,
> +	struct device_attribute *attr, char *buf)
> +{
> +	return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX);
> +}
> +
> +static ssize_t tx_store(struct device *dev,
> +	struct device_attribute *attr, const char *buf, size_t size)
> +{
> +	return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX);
> +}
> +
> +static DEVICE_ATTR_RW(tx);
> +
> +static ssize_t rx_show(struct device *dev,
> +	struct device_attribute *attr, char *buf)
> +{
> +	return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX);
> +}
> +
> +static ssize_t rx_store(struct device *dev,
> +	struct device_attribute *attr, const char *buf, size_t size)
> +{
> +	return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX);
> +}
> +
> +static DEVICE_ATTR_RW(rx);
> +
> +static ssize_t interval_show(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +
> +	return sprintf(buf, "%u\n",
> +		       jiffies_to_msecs(atomic_read(&trigger_data->interval)));
> +}
> +
> +static ssize_t interval_store(struct device *dev,
> +			      struct device_attribute *attr, const char *buf,
> +			      size_t size)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +	unsigned long value;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &value);
> +	if (ret)
> +		return ret;
> +
> +	/* impose some basic bounds on the timer interval */
> +	if (value >= 5 && value <= 10000) {
> +		cancel_delayed_work_sync(&trigger_data->work);
> +
> +		atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
> +		set_baseline_state(trigger_data);	/* resets timer */
> +	}
> +
> +	return size;
> +}
> +
> +static DEVICE_ATTR_RW(interval);
> +
> +static int netdev_trig_notify(struct notifier_block *nb,
> +			      unsigned long evt, void *dv)
> +{
> +	struct net_device *dev =
> +		netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv);
> +	struct led_netdev_data *trigger_data = container_of(nb,
> +							    struct
> +							    led_netdev_data,
> +							    notifier);
> +
> +	if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
> +	    && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
> +	    && evt != NETDEV_CHANGENAME)
> +		return NOTIFY_DONE;
> +
> +	if (strcmp(dev->name, trigger_data->device_name))
> +		return NOTIFY_DONE;
> +
> +	cancel_delayed_work_sync(&trigger_data->work);
> +
> +	spin_lock_bh(&trigger_data->lock);
> +
> +	clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
> +	switch (evt) {
> +	case NETDEV_REGISTER:
> +		if (trigger_data->net_dev)
> +			dev_put(trigger_data->net_dev);
> +		dev_hold(dev);
> +		trigger_data->net_dev = dev;
> +		break;
> +	case NETDEV_CHANGENAME:
> +	case NETDEV_UNREGISTER:
> +		if (trigger_data->net_dev) {
> +			dev_put(trigger_data->net_dev);
> +			trigger_data->net_dev = NULL;
> +		}
> +		break;
> +	case NETDEV_UP:
> +	case NETDEV_CHANGE:
> +		if (netif_carrier_ok(dev))
> +			set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
> +		break;
> +	}
> +
> +	set_baseline_state(trigger_data);
> +
> +	spin_unlock_bh(&trigger_data->lock);
> +
> +	return NOTIFY_DONE;
> +}
> +
> +/* here's the real work! */
> +static void netdev_trig_work(struct work_struct *work)
> +{
> +	struct led_netdev_data *trigger_data = container_of(work,
> +							    struct
> +							    led_netdev_data,
> +							    work.work);
> +	struct rtnl_link_stats64 *dev_stats;
> +	unsigned int new_activity;
> +	struct rtnl_link_stats64 temp;
> +	unsigned long interval;
> +	int invert;
> +
> +	/* If we dont have a device, insure we are off */
> +	if (!trigger_data->net_dev) {
> +		led_set_brightness(trigger_data->led_cdev, LED_OFF);
> +		return;
> +	}
> +
> +	/* If we are not looking for RX/TX then return  */
> +	if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) &&
> +	    !test_bit(NETDEV_LED_RX, &trigger_data->mode))
> +		return;
> +
> +	dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
> +	new_activity =
> +	    (test_bit(NETDEV_LED_TX, &trigger_data->mode) ?
> +		dev_stats->tx_packets : 0) +
> +	    (test_bit(NETDEV_LED_RX, &trigger_data->mode) ?
> +		dev_stats->rx_packets : 0);
> +
> +	if (trigger_data->last_activity != new_activity) {
> +		led_stop_software_blink(trigger_data->led_cdev);
> +
> +		invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode);
> +		interval = jiffies_to_msecs(
> +				atomic_read(&trigger_data->interval));
> +		/* base state is ON (link present) */
> +		led_blink_set_oneshot(trigger_data->led_cdev,
> +				      &interval,
> +				      &interval,
> +				      invert);
> +		trigger_data->last_activity = new_activity;
> +	}
> +
> +	schedule_delayed_work(&trigger_data->work,
> +			(atomic_read(&trigger_data->interval)*2));
> +}
> +
> +static void netdev_trig_activate(struct led_classdev *led_cdev)
> +{
> +	struct led_netdev_data *trigger_data;
> +	int rc;
> +
> +	trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
> +	if (!trigger_data)
> +		return;
> +
> +	spin_lock_init(&trigger_data->lock);
> +
> +	trigger_data->notifier.notifier_call = netdev_trig_notify;
> +	trigger_data->notifier.priority = 10;
> +
> +	INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work);
> +
> +	trigger_data->led_cdev = led_cdev;
> +	trigger_data->net_dev = NULL;
> +	trigger_data->device_name[0] = 0;
> +
> +	trigger_data->mode = 0;
> +	atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
> +	trigger_data->last_activity = 0;
> +
> +	led_cdev->trigger_data = trigger_data;
> +
> +	rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
> +	if (rc)
> +		goto err_out;
> +	rc = device_create_file(led_cdev->dev, &dev_attr_link);
> +	if (rc)
> +		goto err_out_device_name;
> +	rc = device_create_file(led_cdev->dev, &dev_attr_rx);
> +	if (rc)
> +		goto err_out_link;
> +	rc = device_create_file(led_cdev->dev, &dev_attr_tx);
> +	if (rc)
> +		goto err_out_rx;
> +	rc = device_create_file(led_cdev->dev, &dev_attr_interval);
> +	if (rc)
> +		goto err_out_tx;
> +	rc = register_netdevice_notifier(&trigger_data->notifier);
> +	if (rc)
> +		goto err_out_interval;
> +	return;
> +
> +err_out_interval:
> +	device_remove_file(led_cdev->dev, &dev_attr_interval);
> +err_out_tx:
> +	device_remove_file(led_cdev->dev, &dev_attr_tx);
> +err_out_rx:
> +	device_remove_file(led_cdev->dev, &dev_attr_rx);
> +err_out_link:
> +	device_remove_file(led_cdev->dev, &dev_attr_link);
> +err_out_device_name:
> +	device_remove_file(led_cdev->dev, &dev_attr_device_name);
> +err_out:
> +	led_cdev->trigger_data = NULL;
> +	kfree(trigger_data);
> +}
> +
> +static void netdev_trig_deactivate(struct led_classdev *led_cdev)
> +{
> +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
> +
> +	if (trigger_data) {
> +		unregister_netdevice_notifier(&trigger_data->notifier);
> +
> +		device_remove_file(led_cdev->dev, &dev_attr_device_name);
> +		device_remove_file(led_cdev->dev, &dev_attr_link);
> +		device_remove_file(led_cdev->dev, &dev_attr_rx);
> +		device_remove_file(led_cdev->dev, &dev_attr_tx);
> +		device_remove_file(led_cdev->dev, &dev_attr_interval);
> +
> +		cancel_delayed_work_sync(&trigger_data->work);
> +
> +		if (trigger_data->net_dev)
> +			dev_put(trigger_data->net_dev);
> +
> +		kfree(trigger_data);
> +	}
> +}
> +
> +static struct led_trigger netdev_led_trigger = {
> +	.name = "netdev",
> +	.activate = netdev_trig_activate,
> +	.deactivate = netdev_trig_deactivate,
> +};
> +
> +static int __init netdev_trig_init(void)
> +{
> +	return led_trigger_register(&netdev_led_trigger);
> +}
> +
> +static void __exit netdev_trig_exit(void)
> +{
> +	led_trigger_unregister(&netdev_led_trigger);
> +}
> +
> +module_init(netdev_trig_init);
> +module_exit(netdev_trig_exit);
> +
> +MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>");
> +MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
> +MODULE_DESCRIPTION("Netdev LED trigger");
> +MODULE_LICENSE("GPL v2");
> 

Applied to the for-next branch of linux-leds.git.

-- 
Best regards,
Jacek Anaszewski

^ permalink raw reply

* [net-next PATCH 1/1] tipc: add back tipc prefix to log messages
From: John Thompson @ 2017-12-11 21:54 UTC (permalink / raw)
  To: davem, netdev; +Cc: tipc-discussion

The tipc prefix to log messages generated by tipc was
removed in commit 07f6c4bc0 ("tipc: convert tipc reference
table to use generic rhashtable").

This is still a useful prefix and so add it back.

Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: John Thompson <thompa.atl@gmail.com>
---
 net/tipc/core.c | 2 --
 net/tipc/core.h | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/tipc/core.c b/net/tipc/core.c
index 0b982d048fb9..4cd9e57446ec 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -34,8 +34,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */

-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include "core.h"
 #include "name_table.h"
 #include "subscr.h"
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 964342689f2c..f89f9a3c18c2 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -37,6 +37,8 @@
 #ifndef _TIPC_CORE_H
 #define _TIPC_CORE_H

+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/tipc.h>
 #include <linux/tipc_config.h>
 #include <linux/tipc_netlink.h>
-- 
2.15.0
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related

* Re: [REGRESSION][4.13.y][4.14.y][v4.15.y] net: reduce skb_warn_bad_offload() noise
From: Willem de Bruijn @ 2017-12-11 21:56 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Joseph Salisbury, Eric Dumazet, Dmitry Vyukov, Willem de Bruijn,
	David Miller, Daniel Borkmann, jakub.kicinski, linux,
	John Fastabend, me, idosch, Network Development, LKML, stable,
	1715609
In-Reply-To: <20171211214457.GA28858@kroah.com>

On Mon, Dec 11, 2017 at 4:44 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Mon, Dec 11, 2017 at 04:25:26PM -0500, Willem de Bruijn wrote:
>> Note that UFO was removed in 4.14 and that skb_warn_bad_offload
>> can happen for various types of packets, so there may be multiple
>> independent bug reports. I'm investigating two other non-UFO reports
>> just now.
>
> Meta-comment, now that UFO is gone from mainline, I'm wondering if I
> should just delete it from 4.4 and 4.9 as well.  Any objections for
> that?  I'd like to make it easy to maintain these kernels for a while,
> and having them diverge like this, with all of the issues around UFO,
> seems like it will just make life harder for myself if I leave it in.
>
> Any opinions?

Some of that removal had to be reverted with commit 0c19f846d582
("net: accept UFO datagrams from tuntap and packet") for VM live
migration between kernels.

Any backports probably should squash that in at the least. Just today
another thread discussed that that patch may not address all open
issues still, so it may be premature to backport at this point.
http://lkml.kernel.org/r/<d71df64e-e65f-4db4-6f2e-c002c15fcbe4@01019freenet.de>

^ permalink raw reply

* Re: Huge memory leak with 4.15.0-rc2+
From: John Fastabend @ 2017-12-11 22:15 UTC (permalink / raw)
  To: Paweł Staszewski, Linux Kernel Network Developers
In-Reply-To: <2353c149-cae1-f986-63d0-3568534a1e8c@itcare.pl>

On 12/11/2017 01:48 PM, Paweł Staszewski wrote:
> 
> 
> W dniu 2017-12-11 o 22:23, Paweł Staszewski pisze:
>> Hi
>>
>>
>> I just upgraded some testing host to 4.15.0-rc2+ kernel
>>
>> And after some time of traffic processing - when traffic on all ports
>> reach about 3Mpps - memleak started.
>>


[...]

>> Some observations - when i disable tso on all cards there is more
>> memleak.
>>
>>
>>
>>
>>
> When traffic starts to drop - there is less and less memleak
> below link to memory usage graph:
> https://ibb.co/hU97kG
> 
> And there is rising slab_unrecl - Amount of unreclaimable memory used
> for slab kernel allocations
> 
> 
> Forgot to add that im using hfsc and qdiscs like pfifo on classes.
> 
> 

Maybe some error case I missed in the qdisc patches I'm looking into
it.

Thanks,
John

^ permalink raw reply

* Re: [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
From: Tom Herbert @ 2017-12-11 22:16 UTC (permalink / raw)
  To: David Miller
  Cc: Linux Kernel Network Developers, Roopa Prabhu, Rohit LastName
In-Reply-To: <20171211.163416.1305681033764328226.davem@davemloft.net>

On Mon, Dec 11, 2017 at 1:34 PM, David Miller <davem@davemloft.net> wrote:
> From: Tom Herbert <tom@quantonium.net>
> Date: Mon, 11 Dec 2017 12:38:28 -0800
>
>> DOS mitigations:
>>
>> - The number of outstanding resolutions is limited by the size of the
>>   table
>> - Timeout of pending entries limits the number of netlink resolution
>>   messages
>> - Packets are not queued that are pending resolution. In the current
>>   model that can be forwarded to a router that has all reachability
>>   information (ILA use case for example)
>
> None of these mitigation schemes matter.
>
> If packet traffic can influence the table of entries (your cache
> or whatever), then you will be DoS'able.
>
> If you limit outstanding resolutions, you harm legitimate traffic
> whose resolutions will not be processed now too just as equally
> as you will harm "bad guy" traffic.
>
David,

How can we build a system that allows an unlimited number of
resolutions without drop? Unless the resolution path can handle a
higher packet load than the receive path, there will be some place in
the system where memory is allocated and that limits the amount of
pending resolutions (i.e. pending packet skbs, entry in a resolution
table, skbs on a netlink socket).

> If you forward in the case of pending resolution, the bad guy can
> make you forward everything there.  The bad guy can effectively
> make your caching node stop caching completely.
>
But a DOS attack doesn't stop fowarding, at best it forces suboptimal
forwarding. This analogous to when the SYN cache is filled up but SYN
cookies allow forward progress in a degraded operational mode.

Thanks,
Tom

^ permalink raw reply

* Re: Huge memory leak with 4.15.0-rc2+
From: Paweł Staszewski @ 2017-12-11 22:27 UTC (permalink / raw)
  To: John Fastabend, Linux Kernel Network Developers
In-Reply-To: <65a3563d-396e-e4fb-7dad-937ce999868e@gmail.com>



W dniu 2017-12-11 o 23:15, John Fastabend pisze:
> On 12/11/2017 01:48 PM, Paweł Staszewski wrote:
>>
>> W dniu 2017-12-11 o 22:23, Paweł Staszewski pisze:
>>> Hi
>>>
>>>
>>> I just upgraded some testing host to 4.15.0-rc2+ kernel
>>>
>>> And after some time of traffic processing - when traffic on all ports
>>> reach about 3Mpps - memleak started.
>>>
>
> [...]
>
>>> Some observations - when i disable tso on all cards there is more
>>> memleak.
>>>
>>>
>>>
>>>
>>>
>> When traffic starts to drop - there is less and less memleak
>> below link to memory usage graph:
>> https://ibb.co/hU97kG
>>
>> And there is rising slab_unrecl - Amount of unreclaimable memory used
>> for slab kernel allocations
>>
>>
>> Forgot to add that im using hfsc and qdiscs like pfifo on classes.
>>
>>
> Maybe some error case I missed in the qdisc patches I'm looking into
> it.
>
> Thanks,
> John
>
>
This is how it looks like when corelated on graph - traffic vs mem
https://ibb.co/njpkqG

Typical hfsc class + qdisc:
### Client interface vlan1616
tc qdisc del dev vlan1616 root
tc qdisc add dev vlan1616 handle 1: root hfsc default 100
tc class add dev vlan1616 parent 1: classid 1:100 hfsc ls m2 200Mbit ul 
m2 200Mbit
tc qdisc add dev vlan1616 parent 1:100 handle 100: pfifo limit 128
### End TM for client interface
tc qdisc del dev vlan1616 ingress
tc qdisc add dev vlan1616 handle ffff: ingress
tc filter add dev vlan1616 parent ffff: protocol ip prio 50 u32 match ip 
src 0.0.0.0/0 police rate 200Mbit burst 200M mtu 32k drop flowid 1:1

And this is same for about 450 vlan interfaces


Good thing is that compared to 4.14.3 i have about 5% less cpu load on 
4.15.0-rc2+

When hfsc will be lockless or tbf - then it will be really huge 
difference in cpu load on x86 when using traffic shaping - so really 
good job John.

^ permalink raw reply

* Re: [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
From: Tom Herbert @ 2017-12-11 22:32 UTC (permalink / raw)
  To: Tom Herbert
  Cc: David Miller, Linux Kernel Network Developers, Roopa Prabhu,
	Rohit LastName
In-Reply-To: <CAPDqMer_F=uFZ08LytAbU7hwT4d98iYFGfHHFKKtL1mB4a+6qw@mail.gmail.com>

On Mon, Dec 11, 2017 at 2:16 PM, Tom Herbert <tom@quantonium.net> wrote:
> On Mon, Dec 11, 2017 at 1:34 PM, David Miller <davem@davemloft.net> wrote:
>> From: Tom Herbert <tom@quantonium.net>
>> Date: Mon, 11 Dec 2017 12:38:28 -0800
>>
>>> DOS mitigations:
>>>
>>> - The number of outstanding resolutions is limited by the size of the
>>>   table
>>> - Timeout of pending entries limits the number of netlink resolution
>>>   messages
>>> - Packets are not queued that are pending resolution. In the current
>>>   model that can be forwarded to a router that has all reachability
>>>   information (ILA use case for example)
>>
>> None of these mitigation schemes matter.
>>
>> If packet traffic can influence the table of entries (your cache
>> or whatever), then you will be DoS'able.
>>
>> If you limit outstanding resolutions, you harm legitimate traffic
>> whose resolutions will not be processed now too just as equally
>> as you will harm "bad guy" traffic.
>>
> David,
>
Actually, please disregard. I will respin to use secure redirects.

> How can we build a system that allows an unlimited number of
> resolutions without drop? Unless the resolution path can handle a
> higher packet load than the receive path, there will be some place in
> the system where memory is allocated and that limits the amount of
> pending resolutions (i.e. pending packet skbs, entry in a resolution
> table, skbs on a netlink socket).
>
>> If you forward in the case of pending resolution, the bad guy can
>> make you forward everything there.  The bad guy can effectively
>> make your caching node stop caching completely.
>>
> But a DOS attack doesn't stop fowarding, at best it forces suboptimal
> forwarding. This analogous to when the SYN cache is filled up but SYN
> cookies allow forward progress in a degraded operational mode.
>
> Thanks,
> Tom

^ permalink raw reply

* Re: [PATCH net-next v5 1/2] net: add support for Cavium PTP coprocessor
From: Richard Cochran @ 2017-12-11 22:59 UTC (permalink / raw)
  To: Aleksey Makarov
  Cc: netdev, linux-arm-kernel, linux-kernel, Goutham, Sunil,
	Radoslaw Biernacki, Robert Richter, David Daney,
	Philippe Ombredanne
In-Reply-To: <20171211141435.2915-2-aleksey.makarov@cavium.com>


Sorry I didn't finish reviewing before...

On Mon, Dec 11, 2017 at 05:14:30PM +0300, Aleksey Makarov wrote:
> +/**
> + * cavium_ptp_adjfreq() - Adjust ptp frequency
> + * @ptp: PTP clock info
> + * @ppb: how much to adjust by, in parts-per-billion
> + */
> +static int cavium_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)

adjfreq() is deprecated.  See ptp_clock_kernel.h.  Please re-work this
to implement the adjfine() method instead.

> +/**
> + * cavium_ptp_enable() - Check if PTP is enabled

Nit - comment is not correct. This method is for the auxiliary PHC
functions.

> + * @ptp: PTP clock info
> + * @rq:  request
> + * @on:  is it on
> + */
> +static int cavium_ptp_enable(struct ptp_clock_info *ptp_info,
> +			     struct ptp_clock_request *rq, int on)
> +{
> +	return -EOPNOTSUPP;
> +}

...

> +static int cavium_ptp_probe(struct pci_dev *pdev,
> +			    const struct pci_device_id *ent)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct cavium_ptp *clock;
> +	struct cyclecounter *cc;
> +	u64 clock_cfg;
> +	u64 clock_comp;
> +	int err;
> +
> +	clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
> +	if (!clock)
> +		return -ENOMEM;
> +
> +	clock->pdev = pdev;
> +
> +	err = pcim_enable_device(pdev);
> +	if (err)
> +		return err;
> +
> +	err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
> +	if (err)
> +		return err;
> +
> +	clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
> +
> +	spin_lock_init(&clock->spin_lock);
> +
> +	cc = &clock->cycle_counter;
> +	cc->read = cavium_ptp_cc_read;
> +	cc->mask = CYCLECOUNTER_MASK(64);
> +	cc->mult = 1;
> +	cc->shift = 0;
> +
> +	timecounter_init(&clock->time_counter, &clock->cycle_counter,
> +			 ktime_to_ns(ktime_get_real()));
> +
> +	clock->clock_rate = ptp_cavium_clock_get();
> +
> +	clock->ptp_info = (struct ptp_clock_info) {
> +		.owner		= THIS_MODULE,
> +		.name		= "ThunderX PTP",
> +		.max_adj	= 1000000000ull,
> +		.n_ext_ts	= 0,
> +		.n_pins		= 0,
> +		.pps		= 0,
> +		.adjfreq	= cavium_ptp_adjfreq,
> +		.adjtime	= cavium_ptp_adjtime,
> +		.gettime64	= cavium_ptp_gettime,
> +		.settime64	= cavium_ptp_settime,
> +		.enable		= cavium_ptp_enable,
> +	};
> +
> +	clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
> +	clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
> +	writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
> +
> +	clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate;
> +	writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP);
> +
> +	clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev);
> +	if (IS_ERR(clock->ptp_clock)) {

You need to handle the case when ptp_clock_register() returns NULL.

from ptp_clock_kernel.h:

/**
 * ptp_clock_register() - register a PTP hardware clock driver
 *
 * @info:   Structure describing the new clock.
 * @parent: Pointer to the parent device of the new clock.
 *
 * Returns a valid pointer on success or PTR_ERR on failure.  If PHC
 * support is missing at the configuration level, this function
 * returns NULL, and drivers are expected to gracefully handle that
 * case separately.
 */

> +		clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
> +		clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
> +		writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
> +		return PTR_ERR(clock->ptp_clock);
> +	}
> +
> +	pci_set_drvdata(pdev, clock);
> +	return 0;
> +}

Thanks,
Richard

^ permalink raw reply

* Re: [PATCH 1/3] PCI: introduce a device-managed version of pci_set_mwi
From: Bjorn Helgaas @ 2017-12-11 23:00 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Realtek linux nic maintainers, Bjorn Helgaas,
	netdev@vger.kernel.org, linux-pci@vger.kernel.org
In-Reply-To: <3e560e2b-7f11-74e2-6db5-60c8479dc59b@gmail.com>

On Sun, Dec 10, 2017 at 12:43:48AM +0100, Heiner Kallweit wrote:
> Introduce a device-managed version of pci_set_mwi. First user is the
> Realtek r8169 driver.
> 
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>

With the subject and changelog as follows and the code reordering below,

  PCI: Add pcim_set_mwi(), a device-managed pci_set_mwi()

  Add pcim_set_mwi(), a device-managed version of pci_set_mwi(). First user
  is the Realtek r8169 driver.

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

With these changes, feel free to merge with the series via the netdev
tree.

> ---
>  drivers/pci/pci.c   | 29 +++++++++++++++++++++++++++++
>  include/linux/pci.h |  1 +
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 4a7c6864f..fc57c378d 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1458,6 +1458,7 @@ struct pci_devres {
>  	unsigned int pinned:1;
>  	unsigned int orig_intx:1;
>  	unsigned int restore_intx:1;
> +	unsigned int mwi:1;
>  	u32 region_mask;
>  };
>  
> @@ -1476,6 +1477,9 @@ static void pcim_release(struct device *gendev, void *res)
>  		if (this->region_mask & (1 << i))
>  			pci_release_region(dev, i);
>  
> +	if (this->mwi)
> +		pci_clear_mwi(dev);
> +
>  	if (this->restore_intx)
>  		pci_intx(dev, this->orig_intx);
>  
> @@ -3760,6 +3764,31 @@ int pci_set_mwi(struct pci_dev *dev)
>  }
>  EXPORT_SYMBOL(pci_set_mwi);
>  
> +/**
> + * pcim_set_mwi - Managed pci_set_mwi()
> + * @dev: the PCI device for which MWI is enabled
> + *
> + * Managed pci_set_mwi().
> + *
> + * RETURNS: An appropriate -ERRNO error value on error, or zero for success.

> + */
> +int pcim_set_mwi(struct pci_dev *dev)
> +{
> +	struct pci_devres *dr;
> +	int ret;
> +
> +	ret = pci_set_mwi(dev);
> +	if (ret)
> +		return ret;
> +
> +	dr = find_pci_dr(dev);
> +	if (dr)
> +		dr->mwi = 1;
> +
> +	return 0;

I would rather look up the pci_devres first, e.g.,

  dr = find_pci_dr(dev);
  if (!dr)
    return -ENOMEM;

  dr->mwi = 1;
  return pci_set_mwi(dev);

That way we won't enable MWI and be unable to disable it at release-time.

> +}
> +EXPORT_SYMBOL(pcim_set_mwi);
> +
>  /**
>   * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
>   * @dev: the PCI device for which MWI is enabled
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 978aad784..0a7ac863a 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1064,6 +1064,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
>  int pci_set_cacheline_size(struct pci_dev *dev);
>  #define HAVE_PCI_SET_MWI
>  int __must_check pci_set_mwi(struct pci_dev *dev);
> +int __must_check pcim_set_mwi(struct pci_dev *dev);
>  int pci_try_set_mwi(struct pci_dev *dev);
>  void pci_clear_mwi(struct pci_dev *dev);
>  void pci_intx(struct pci_dev *dev, int enable);
> -- 
> 2.15.1
> 
> 

^ permalink raw reply

* [PATCH v3] net: ethernet: arc: fix error handling in emac_rockchip_probe
From: Branislav Radocaj @ 2017-12-11 23:13 UTC (permalink / raw)
  To: heiko, netdev
  Cc: linux-arm-kernel, linux-rockchip, linux-kernel, Branislav Radocaj

If clk_set_rate() fails, we should disable clk before return.
Found by Linux Driver Verification project (linuxtesting.org).

Changes since v2 [1]:
* Merged with latest code changes

Changes since v1:
Update made thanks to David's review, much appreciated David.
* Improved inconsistent failure handling of clock rate setting
* For completeness of usecase, added arc_emac_probe error handling

Signed-off-by: Branislav Radocaj <branislav@radocaj.org>
---
[1] https://marc.info/?l=linux-netdev&m=151301239802445&w=2
---
 drivers/net/ethernet/arc/emac_rockchip.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
index c6163874e4e7..16f9bee992fe 100644
--- a/drivers/net/ethernet/arc/emac_rockchip.c
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
@@ -199,9 +199,11 @@ static int emac_rockchip_probe(struct platform_device *pdev)
 
 	/* RMII interface needs always a rate of 50MHz */
 	err = clk_set_rate(priv->refclk, 50000000);
-	if (err)
+	if (err) {
 		dev_err(dev,
 			"failed to change reference clock rate (%d)\n", err);
+		goto out_regulator_disable;
+	}
 
 	if (priv->soc_data->need_div_macclk) {
 		priv->macclk = devm_clk_get(dev, "macclk");
@@ -230,12 +232,14 @@ static int emac_rockchip_probe(struct platform_device *pdev)
 	err = arc_emac_probe(ndev, interface);
 	if (err) {
 		dev_err(dev, "failed to probe arc emac (%d)\n", err);
-		goto out_regulator_disable;
+		goto out_clk_disable_macclk;
 	}
 
 	return 0;
+
 out_clk_disable_macclk:
-	clk_disable_unprepare(priv->macclk);
+	if (priv->soc_data->need_div_macclk)
+		clk_disable_unprepare(priv->macclk);
 out_regulator_disable:
 	if (priv->regulator)
 		regulator_disable(priv->regulator);
-- 
2.11.0

^ permalink raw reply related

* [PATCH] Fix handling of verdicts after NF_QUEUE
From: Debabrata Banerjee @ 2017-12-11 23:30 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: David S . Miller, netfilter-devel, coreteam, netdev, stable,
	dbanerje

A verdict of NF_STOLEN after NF_QUEUE will cause an incorrect return value
and a potential kernel panic via double free of skb's

This was broken by commit 7034b566a4e7 ("netfilter: fix nf_queue handling")
and subsequently fixed in v4.10 by commit c63cbc460419 ("netfilter:
use switch() to handle verdict cases from nf_hook_slow()"). However that
commit cannot be cleanly cherry-picked to v4.9

Signed-off-by: Debabrata Banerjee <dbanerje@akamai.com>

---

This fix is only needed for v4.9 stable since v4.10+ does not have the
issue
---
 net/netfilter/core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 004af030ef1a..d869ea50623e 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -364,6 +364,11 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
 		ret = nf_queue(skb, state, &entry, verdict);
 		if (ret == 1 && entry)
 			goto next_hook;
+	} else {
+		/* Implicit handling for NF_STOLEN, as well as any other
+		 * non conventional verdicts.
+		 */
+		ret = 0;
 	}
 	return ret;
 }
-- 
2.15.1

^ permalink raw reply related

* Re: [PATCH net-next v5 2/2] net: thunderx: add timestamping support
From: Richard Cochran @ 2017-12-11 23:32 UTC (permalink / raw)
  To: Aleksey Makarov
  Cc: netdev, linux-arm-kernel, linux-kernel, Goutham, Sunil,
	Radoslaw Biernacki, Robert Richter, David Daney,
	Philippe Ombredanne, Sunil Goutham
In-Reply-To: <20171211141435.2915-3-aleksey.makarov@cavium.com>

On Mon, Dec 11, 2017 at 05:14:31PM +0300, Aleksey Makarov wrote:
> diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
> index 4a02e618e318..204b234beb9d 100644
> --- a/drivers/net/ethernet/cavium/thunder/nic.h
> +++ b/drivers/net/ethernet/cavium/thunder/nic.h
> @@ -263,6 +263,8 @@ struct nicvf_drv_stats {
>  	struct u64_stats_sync   syncp;
>  };
>  
> +struct cavium_ptp;
> +
>  struct nicvf {
>  	struct nicvf		*pnicvf;
>  	struct net_device	*netdev;
> @@ -312,6 +314,12 @@ struct nicvf {
>  	struct tasklet_struct	qs_err_task;
>  	struct work_struct	reset_task;
>  
> +	/* PTP timestamp */
> +	struct cavium_ptp	*ptp_clock;
> +	bool			hw_rx_tstamp;
> +	struct sk_buff		*ptp_skb;
> +	atomic_t		tx_ptp_skbs;

It is disturbing that the above two fields are set in different
places.  Shouldn't they be unified into one logical lock?

Here you clear them together:

> +static void nicvf_snd_ptp_handler(struct net_device *netdev,
> +				  struct cqe_send_t *cqe_tx)
> +{
> +	struct nicvf *nic = netdev_priv(netdev);
> +	struct skb_shared_hwtstamps ts;
> +	u64 ns;
> +
> +	nic = nic->pnicvf;
> +
> +	/* Sync for 'ptp_skb' */
> +	smp_rmb();
> +
> +	/* New timestamp request can be queued now */
> +	atomic_set(&nic->tx_ptp_skbs, 0);
> +
> +	/* Check for timestamp requested skb */
> +	if (!nic->ptp_skb)
> +		return;
> +
> +	/* Check if timestamping is timedout, which is set to 10us */
> +	if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT ||
> +	    cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT)
> +		goto no_tstamp;
> +
> +	/* Get the timestamp */
> +	memset(&ts, 0, sizeof(ts));
> +	ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp);
> +	ts.hwtstamp = ns_to_ktime(ns);
> +	skb_tstamp_tx(nic->ptp_skb, &ts);
> +
> +no_tstamp:
> +	/* Free the original skb */
> +	dev_kfree_skb_any(nic->ptp_skb);
> +	nic->ptp_skb = NULL;
> +	/* Sync 'ptp_skb' */
> +	smp_wmb();
> +}
> +

but here you set the one:

> @@ -657,7 +697,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
>  		prefetch(skb);
>  		(*tx_pkts)++;
>  		*tx_bytes += skb->len;
> -		napi_consume_skb(skb, budget);
> +		/* If timestamp is requested for this skb, don't free it */
> +		if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
> +		    !nic->pnicvf->ptp_skb)
> +			nic->pnicvf->ptp_skb = skb;
> +		else
> +			napi_consume_skb(skb, budget);
>  		sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
>  	} else {
>  		/* In case of SW TSO on 88xx, only last segment will have

here you clear one:

> @@ -1319,12 +1382,28 @@ int nicvf_stop(struct net_device *netdev)
>  
>  	nicvf_free_cq_poll(nic);
>  
> +	/* Free any pending SKB saved to receive timestamp */
> +	if (nic->ptp_skb) {
> +		dev_kfree_skb_any(nic->ptp_skb);
> +		nic->ptp_skb = NULL;
> +	}
> +
>  	/* Clear multiqset info */
>  	nic->pnicvf = nic;
>  
>  	return 0;
>  }

here you clear both:

> @@ -1394,6 +1473,12 @@ int nicvf_open(struct net_device *netdev)
>  	if (nic->sqs_mode)
>  		nicvf_get_primary_vf_struct(nic);
>  
> +	/* Configure PTP timestamp */
> +	if (nic->ptp_clock)
> +		nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
> +	atomic_set(&nic->tx_ptp_skbs, 0);
> +	nic->ptp_skb = NULL;
> +
>  	/* Configure receive side scaling and MTU */
>  	if (!nic->sqs_mode) {
>  		nicvf_rss_init(nic);

here you set the other:

> @@ -1385,6 +1388,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
>  		hdr->inner_l3_offset = skb_network_offset(skb) - 2;
>  		this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
>  	}
> +
> +	/* Check if timestamp is requested */
> +	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
> +		skb_tx_timestamp(skb);
> +		return;
> +	}
> +
> +	/* Tx timestamping not supported along with TSO, so ignore request */
> +	if (skb_shinfo(skb)->gso_size)
> +		return;
> +
> +	/* HW supports only a single outstanding packet to timestamp */
> +	if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1))
> +		return;
> +
> +	/* Mark the SKB for later reference */
> +	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> +
> +	/* Finally enable timestamp generation
> +	 * Since 'post_cqe' is also set, two CQEs will be posted
> +	 * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP.
> +	 */
> +	hdr->tstmp = 1;
>  }

and so it is completely non-obvious whether this is race free or not.

Thanks,
Richard

^ permalink raw reply

* [Patch net-next] net_sched: switch to exit_batch for action pernet ops
From: Cong Wang @ 2017-12-11 23:35 UTC (permalink / raw)
  To: netdev; +Cc: Cong Wang, Jamal Hadi Salim, Jiri Pirko

Since we now hold RTNL lock in tc_action_net_exit(), it is good to
batch them to speedup tc action dismantle.

Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 include/net/act_api.h      | 13 ++++++++++---
 net/sched/act_bpf.c        |  8 +++-----
 net/sched/act_connmark.c   |  8 +++-----
 net/sched/act_csum.c       |  8 +++-----
 net/sched/act_gact.c       |  8 +++-----
 net/sched/act_ife.c        |  8 +++-----
 net/sched/act_ipt.c        | 16 ++++++----------
 net/sched/act_mirred.c     |  8 +++-----
 net/sched/act_nat.c        |  8 +++-----
 net/sched/act_pedit.c      |  8 +++-----
 net/sched/act_police.c     |  8 +++-----
 net/sched/act_sample.c     |  8 +++-----
 net/sched/act_simple.c     |  8 +++-----
 net/sched/act_skbedit.c    |  8 +++-----
 net/sched/act_skbmod.c     |  8 +++-----
 net/sched/act_tunnel_key.c |  8 +++-----
 net/sched/act_vlan.c       |  8 +++-----
 17 files changed, 61 insertions(+), 88 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 02bf409140d0..6ed9692f20bd 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -120,12 +120,19 @@ int tc_action_net_init(struct tc_action_net *tn,
 void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
 			 struct tcf_idrinfo *idrinfo);
 
-static inline void tc_action_net_exit(struct tc_action_net *tn)
+static inline void tc_action_net_exit(struct list_head *net_list,
+				      unsigned int id)
 {
+	struct net *net;
+
 	rtnl_lock();
-	tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
+	list_for_each_entry(net, net_list, exit_list) {
+		struct tc_action_net *tn = net_generic(net, id);
+
+		tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
+		kfree(tn->idrinfo);
+	}
 	rtnl_unlock();
-	kfree(tn->idrinfo);
 }
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index e6c477fa9ca5..b3f2c15affa7 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -401,16 +401,14 @@ static __net_init int bpf_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_bpf_ops);
 }
 
-static void __net_exit bpf_exit_net(struct net *net)
+static void __net_exit bpf_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, bpf_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, bpf_net_id);
 }
 
 static struct pernet_operations bpf_net_ops = {
 	.init = bpf_init_net,
-	.exit = bpf_exit_net,
+	.exit_batch = bpf_exit_net,
 	.id   = &bpf_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 10b7a8855a6c..2b15ba84e0c8 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -209,16 +209,14 @@ static __net_init int connmark_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_connmark_ops);
 }
 
-static void __net_exit connmark_exit_net(struct net *net)
+static void __net_exit connmark_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, connmark_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, connmark_net_id);
 }
 
 static struct pernet_operations connmark_net_ops = {
 	.init = connmark_init_net,
-	.exit = connmark_exit_net,
+	.exit_batch = connmark_exit_net,
 	.id   = &connmark_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index d836f998117b..af4b8ec60d9a 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -635,16 +635,14 @@ static __net_init int csum_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_csum_ops);
 }
 
-static void __net_exit csum_exit_net(struct net *net)
+static void __net_exit csum_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, csum_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, csum_net_id);
 }
 
 static struct pernet_operations csum_net_ops = {
 	.init = csum_init_net,
-	.exit = csum_exit_net,
+	.exit_batch = csum_exit_net,
 	.id   = &csum_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e29a48ef7fc3..9d632e92cad0 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -235,16 +235,14 @@ static __net_init int gact_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_gact_ops);
 }
 
-static void __net_exit gact_exit_net(struct net *net)
+static void __net_exit gact_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, gact_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, gact_net_id);
 }
 
 static struct pernet_operations gact_net_ops = {
 	.init = gact_init_net,
-	.exit = gact_exit_net,
+	.exit_batch = gact_exit_net,
 	.id   = &gact_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index dee9cf22686c..5954e992685a 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -858,16 +858,14 @@ static __net_init int ife_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_ife_ops);
 }
 
-static void __net_exit ife_exit_net(struct net *net)
+static void __net_exit ife_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, ife_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, ife_net_id);
 }
 
 static struct pernet_operations ife_net_ops = {
 	.init = ife_init_net,
-	.exit = ife_exit_net,
+	.exit_batch = ife_exit_net,
 	.id   = &ife_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 2479b255dc1d..06e380ae0928 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -337,16 +337,14 @@ static __net_init int ipt_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_ipt_ops);
 }
 
-static void __net_exit ipt_exit_net(struct net *net)
+static void __net_exit ipt_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, ipt_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, ipt_net_id);
 }
 
 static struct pernet_operations ipt_net_ops = {
 	.init = ipt_init_net,
-	.exit = ipt_exit_net,
+	.exit_batch = ipt_exit_net,
 	.id   = &ipt_net_id,
 	.size = sizeof(struct tc_action_net),
 };
@@ -387,16 +385,14 @@ static __net_init int xt_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_xt_ops);
 }
 
-static void __net_exit xt_exit_net(struct net *net)
+static void __net_exit xt_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, xt_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, xt_net_id);
 }
 
 static struct pernet_operations xt_net_ops = {
 	.init = xt_init_net,
-	.exit = xt_exit_net,
+	.exit_batch = xt_exit_net,
 	.id   = &xt_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index cee2d413bf57..37e5e4decbd6 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -334,16 +334,14 @@ static __net_init int mirred_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_mirred_ops);
 }
 
-static void __net_exit mirred_exit_net(struct net *net)
+static void __net_exit mirred_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, mirred_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, mirred_net_id);
 }
 
 static struct pernet_operations mirred_net_ops = {
 	.init = mirred_init_net,
-	.exit = mirred_exit_net,
+	.exit_batch = mirred_exit_net,
 	.id   = &mirred_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index c365d01b99c8..98c6a4b2f523 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -310,16 +310,14 @@ static __net_init int nat_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_nat_ops);
 }
 
-static void __net_exit nat_exit_net(struct net *net)
+static void __net_exit nat_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, nat_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, nat_net_id);
 }
 
 static struct pernet_operations nat_net_ops = {
 	.init = nat_init_net,
-	.exit = nat_exit_net,
+	.exit_batch = nat_exit_net,
 	.id   = &nat_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index dba996bcd6dc..349beaffb29e 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -453,16 +453,14 @@ static __net_init int pedit_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_pedit_ops);
 }
 
-static void __net_exit pedit_exit_net(struct net *net)
+static void __net_exit pedit_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, pedit_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, pedit_net_id);
 }
 
 static struct pernet_operations pedit_net_ops = {
 	.init = pedit_init_net,
-	.exit = pedit_exit_net,
+	.exit_batch = pedit_exit_net,
 	.id   = &pedit_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 3bb2ebf9e9ae..bf483db993a1 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -334,16 +334,14 @@ static __net_init int police_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_police_ops);
 }
 
-static void __net_exit police_exit_net(struct net *net)
+static void __net_exit police_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, police_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, police_net_id);
 }
 
 static struct pernet_operations police_net_ops = {
 	.init = police_init_net,
-	.exit = police_exit_net,
+	.exit_batch = police_exit_net,
 	.id   = &police_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index 859a93903339..1ba0df238756 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -236,16 +236,14 @@ static __net_init int sample_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_sample_ops);
 }
 
-static void __net_exit sample_exit_net(struct net *net)
+static void __net_exit sample_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, sample_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, sample_net_id);
 }
 
 static struct pernet_operations sample_net_ops = {
 	.init = sample_init_net,
-	.exit = sample_exit_net,
+	.exit_batch = sample_exit_net,
 	.id   = &sample_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index eda57b47a6b6..425eac11f6da 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -204,16 +204,14 @@ static __net_init int simp_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_simp_ops);
 }
 
-static void __net_exit simp_exit_net(struct net *net)
+static void __net_exit simp_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, simp_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, simp_net_id);
 }
 
 static struct pernet_operations simp_net_ops = {
 	.init = simp_init_net,
-	.exit = simp_exit_net,
+	.exit_batch = simp_exit_net,
 	.id   = &simp_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 59949d61f20d..5a3f691bb545 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -241,16 +241,14 @@ static __net_init int skbedit_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_skbedit_ops);
 }
 
-static void __net_exit skbedit_exit_net(struct net *net)
+static void __net_exit skbedit_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, skbedit_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, skbedit_net_id);
 }
 
 static struct pernet_operations skbedit_net_ops = {
 	.init = skbedit_init_net,
-	.exit = skbedit_exit_net,
+	.exit_batch = skbedit_exit_net,
 	.id   = &skbedit_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index f090bba1a79e..fa975262dbac 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -266,16 +266,14 @@ static __net_init int skbmod_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_skbmod_ops);
 }
 
-static void __net_exit skbmod_exit_net(struct net *net)
+static void __net_exit skbmod_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, skbmod_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, skbmod_net_id);
 }
 
 static struct pernet_operations skbmod_net_ops = {
 	.init = skbmod_init_net,
-	.exit = skbmod_exit_net,
+	.exit_batch = skbmod_exit_net,
 	.id   = &skbmod_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 57b63bdec3ae..0e23aac09ad6 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -325,16 +325,14 @@ static __net_init int tunnel_key_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_tunnel_key_ops);
 }
 
-static void __net_exit tunnel_key_exit_net(struct net *net)
+static void __net_exit tunnel_key_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, tunnel_key_net_id);
 }
 
 static struct pernet_operations tunnel_key_net_ops = {
 	.init = tunnel_key_init_net,
-	.exit = tunnel_key_exit_net,
+	.exit_batch = tunnel_key_exit_net,
 	.id   = &tunnel_key_net_id,
 	.size = sizeof(struct tc_action_net),
 };
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 41f0878ad26e..e1a1b3f3983a 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -301,16 +301,14 @@ static __net_init int vlan_init_net(struct net *net)
 	return tc_action_net_init(tn, &act_vlan_ops);
 }
 
-static void __net_exit vlan_exit_net(struct net *net)
+static void __net_exit vlan_exit_net(struct list_head *net_list)
 {
-	struct tc_action_net *tn = net_generic(net, vlan_net_id);
-
-	tc_action_net_exit(tn);
+	tc_action_net_exit(net_list, vlan_net_id);
 }
 
 static struct pernet_operations vlan_net_ops = {
 	.init = vlan_init_net,
-	.exit = vlan_exit_net,
+	.exit_batch = vlan_exit_net,
 	.id   = &vlan_net_id,
 	.size = sizeof(struct tc_action_net),
 };
-- 
2.13.0

^ permalink raw reply related

* Re: [PATCH net-next v5 2/2] net: thunderx: add timestamping support
From: Richard Cochran @ 2017-12-11 23:36 UTC (permalink / raw)
  To: Aleksey Makarov
  Cc: netdev, linux-arm-kernel, linux-kernel, Goutham, Sunil,
	Radoslaw Biernacki, Robert Richter, David Daney,
	Philippe Ombredanne, Sunil Goutham
In-Reply-To: <20171211141435.2915-3-aleksey.makarov@cavium.com>

On Mon, Dec 11, 2017 at 05:14:31PM +0300, Aleksey Makarov wrote:
> @@ -880,6 +889,46 @@ static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
>  	}
>  }
>  
> +/* Enable or disable HW timestamping by BGX for pkts received on a LMAC */
> +static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
> +{
> +	struct pkind_cfg *pkind;
> +	u8 lmac, bgx_idx;
> +	u64 pkind_val, pkind_idx;
> +
> +	if (vf >= nic->num_vf_en)
> +		return;
> +
> +	bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
> +	lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
> +
> +	pkind_idx = lmac + bgx_idx * MAX_LMAC_PER_BGX;
> +	pkind_val = nic_reg_read(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3));
> +	pkind = (struct pkind_cfg *)&pkind_val;
> +
> +	if (ptp->enable && !pkind->hdr_sl) {
> +		/* Skiplen to exclude 8byte timestamp while parsing pkt
> +		 * If not configured, will result in L2 errors.
> +		 */
> +		pkind->hdr_sl = 4;
> +		/* Adjust max packet length allowed */
> +		pkind->maxlen += (pkind->hdr_sl * 2);
> +		bgx_config_timestamping(nic->node, bgx_idx, lmac, true);
> +		nic_reg_write(nic,
> +			      NIC_PF_RX_ETYPE_0_7 | (1 << 3),
> +			      (ETYPE_ALG_ENDPARSE << 16) | ETH_P_1588);

don't need three lines for this function call.

> +	} else if (!ptp->enable && pkind->hdr_sl) {
> +		pkind->maxlen -= (pkind->hdr_sl * 2);
> +		pkind->hdr_sl = 0;
> +		bgx_config_timestamping(nic->node, bgx_idx, lmac, false);
> +		nic_reg_write(nic,
> +			      NIC_PF_RX_ETYPE_0_7 | (1 << 3),
> +			      (1ULL << 16) | ETH_P_8021Q); /* reset value */

here neither.  Also avoid comment on the LHS.  If 1<<16 means "reset"
then just define a macro.

> +	}
> +
> +	nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
> +}
> +

Thanks,
Richard

^ permalink raw reply

* [PATCH net-next] tcp: allow TLP in ECN CWR
From: Yuchung Cheng @ 2017-12-11 23:42 UTC (permalink / raw)
  To: davem; +Cc: netdev, ncardwell, edumazet, nanditad, sibanez, Yuchung Cheng

From: Neal Cardwell <ncardwell@google.com>

This patch enables tail loss probe in cwnd reduction (CWR) state
to detect potential losses. Prior to this patch, since the sender
uses PRR to determine the cwnd in CWR state, the combination of
CWR+PRR plus tcp_tso_should_defer() could cause unnecessary stalls
upon losses: PRR makes cwnd so gentle that tcp_tso_should_defer()
defers sending wait for more ACKs. The ACKs may not come due to
packet losses.

Disallowing TLP when there is unused cwnd had the primary effect
of disallowing TLP when there is TSO deferral, Nagle deferral,
or we hit the rwin limit. Because basically every application
write() or incoming ACK will cause us to run tcp_write_xmit()
to see if we can send more, and then if we sent something we call
tcp_schedule_loss_probe() to see if we should schedule a TLP. At
that point, there are a few common reasons why some cwnd budget
could still be unused:

(a) rwin limit
(b) nagle check
(c) TSO deferral
(d) TSQ

For (d), after the next packet tx completion the TSQ mechanism
will allow us to send more packets, so we don't really need a
TLP (in practice it shouldn't matter whether we schedule one
or not). But for (a), (b), (c) the sender won't send any more
packets until it gets another ACK. But if the whole flight was
lost, or all the ACKs were lost, then we won't get any more ACKs,
and ideally we should schedule and send a TLP to get more feedback.
In particular for a long time we have wanted some kind of timer for
TSO deferral, and at least this would give us some kind of timer

Reported-by: Steve Ibanez <sibanez@stanford.edu>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Reviewed-by: Nandita Dukkipati <nanditad@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/tcp_output.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a4d214c7b506..04be9f833927 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2414,15 +2414,12 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto)
 
 	early_retrans = sock_net(sk)->ipv4.sysctl_tcp_early_retrans;
 	/* Schedule a loss probe in 2*RTT for SACK capable connections
-	 * in Open state, that are either limited by cwnd or application.
+	 * not in loss recovery, that are either limited by cwnd or application.
 	 */
 	if ((early_retrans != 3 && early_retrans != 4) ||
 	    !tp->packets_out || !tcp_is_sack(tp) ||
-	    icsk->icsk_ca_state != TCP_CA_Open)
-		return false;
-
-	if ((tp->snd_cwnd > tcp_packets_in_flight(tp)) &&
-	     !tcp_write_queue_empty(sk))
+	    (icsk->icsk_ca_state != TCP_CA_Open &&
+	     icsk->icsk_ca_state != TCP_CA_CWR))
 		return false;
 
 	/* Probe timeout is 2*rtt. Add minimum RTO to account
-- 
2.15.1.424.g9478a66081-goog

^ permalink raw reply related

* [PATCH] igb: Free IRQs when device is hotplugged
From: Lyude Paul @ 2017-12-11 23:45 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: Todd Fujinaka, stable, Jeff Kirsher, netdev, linux-kernel

Recently I got a Caldigit TS3 Thunderbolt 3 dock, and noticed that upon
hotplugging my kernel would immediately crash due to igb:

[  680.825801] kernel BUG at drivers/pci/msi.c:352!
[  680.828388] invalid opcode: 0000 [#1] SMP
[  680.829194] Modules linked in: igb(O) thunderbolt i2c_algo_bit joydev vfat fat btusb btrtl btbcm btintel bluetooth ecdh_generic hp_wmi sparse_keymap rfkill wmi_bmof iTCO_wdt intel_rapl x86_pkg_temp_thermal coretemp crc32_pclmul snd_pcm rtsx_pci_ms mei_me snd_timer memstick snd pcspkr mei soundcore i2c_i801 tpm_tis psmouse shpchp wmi tpm_tis_core tpm video hp_wireless acpi_pad rtsx_pci_sdmmc mmc_core crc32c_intel serio_raw rtsx_pci mfd_core xhci_pci xhci_hcd i2c_hid i2c_core [last unloaded: igb]
[  680.831085] CPU: 1 PID: 78 Comm: kworker/u16:1 Tainted: G           O     4.15.0-rc3Lyude-Test+ #6
[  680.831596] Hardware name: HP HP ZBook Studio G4/826B, BIOS P71 Ver. 01.03 06/09/2017
[  680.832168] Workqueue: kacpi_hotplug acpi_hotplug_work_fn
[  680.832687] RIP: 0010:free_msi_irqs+0x180/0x1b0
[  680.833271] RSP: 0018:ffffc9000030fbf0 EFLAGS: 00010286
[  680.833761] RAX: ffff8803405f9c00 RBX: ffff88033e3d2e40 RCX: 000000000000002c
[  680.834278] RDX: 0000000000000000 RSI: 00000000000000ac RDI: ffff880340be2178
[  680.834832] RBP: 0000000000000000 R08: ffff880340be1ff0 R09: ffff8803405f9c00
[  680.835342] R10: 0000000000000000 R11: 0000000000000040 R12: ffff88033d63a298
[  680.835822] R13: ffff88033d63a000 R14: 0000000000000060 R15: ffff880341959000
[  680.836332] FS:  0000000000000000(0000) GS:ffff88034f440000(0000) knlGS:0000000000000000
[  680.836817] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  680.837360] CR2: 000055e64044afdf CR3: 0000000001c09002 CR4: 00000000003606e0
[  680.837954] Call Trace:
[  680.838853]  pci_disable_msix+0xce/0xf0
[  680.839616]  igb_reset_interrupt_capability+0x5d/0x60 [igb]
[  680.840278]  igb_remove+0x9d/0x110 [igb]
[  680.840764]  pci_device_remove+0x36/0xb0
[  680.841279]  device_release_driver_internal+0x157/0x220
[  680.841739]  pci_stop_bus_device+0x7d/0xa0
[  680.842255]  pci_stop_bus_device+0x2b/0xa0
[  680.842722]  pci_stop_bus_device+0x3d/0xa0
[  680.843189]  pci_stop_and_remove_bus_device+0xe/0x20
[  680.843627]  trim_stale_devices+0xf3/0x140
[  680.844086]  trim_stale_devices+0x94/0x140
[  680.844532]  trim_stale_devices+0xa6/0x140
[  680.845031]  ? get_slot_status+0x90/0xc0
[  680.845536]  acpiphp_check_bridge.part.5+0xfe/0x140
[  680.846021]  acpiphp_hotplug_notify+0x175/0x200
[  680.846581]  ? free_bridge+0x100/0x100
[  680.847113]  acpi_device_hotplug+0x8a/0x490
[  680.847535]  acpi_hotplug_work_fn+0x1a/0x30
[  680.848076]  process_one_work+0x182/0x3a0
[  680.848543]  worker_thread+0x2e/0x380
[  680.848963]  ? process_one_work+0x3a0/0x3a0
[  680.849373]  kthread+0x111/0x130
[  680.849776]  ? kthread_create_worker_on_cpu+0x50/0x50
[  680.850188]  ret_from_fork+0x1f/0x30
[  680.850601] Code: 43 14 85 c0 0f 84 d5 fe ff ff 31 ed eb 0f 83 c5 01 39 6b 14 0f 86 c5 fe ff ff 8b 7b 10 01 ef e8 b7 e4 d2 ff 48 83 78 70 00 74 e3 <0f> 0b 49 8d b5 a0 00 00 00 e8 62 6f d3 ff e9 c7 fe ff ff 48 8b
[  680.851497] RIP: free_msi_irqs+0x180/0x1b0 RSP: ffffc9000030fbf0

As it turns out, normally the freeing of IRQs that would fix this is called
inside of the scope of __igb_close(). However, since the device is
already gone by the point we try to unregister the netdevice from the
driver due to a hotplug we end up seeing that the netif isn't present
and thus, forget to free any of the device IRQs.

So: after unregistering the netdev in igb_remove() check whether the PCI
device is stale and if so, free it's IRQs and tx/rx resources.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 9474933caf21 ("igb: close/suspend race in netif_device_detach")
Cc: Todd Fujinaka <todd.fujinaka@intel.com>
Cc: stable@vger.kernel.org
---
 drivers/net/ethernet/intel/igb/igb_main.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index c208753ff5b7..e650348b4bd7 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3325,6 +3325,16 @@ static void igb_remove(struct pci_dev *pdev)
 
 	unregister_netdev(netdev);
 
+	/* If the PCI device has already been physically removed (e.g. user
+	 * unplugged a thunderbolt dock containing our hw) then the netif will
+	 * already be down, so unregistering the netdev won't free the IRQs
+	 */
+	if (!pci_device_is_present(pdev)) {
+		igb_free_irq(adapter);
+		igb_free_all_tx_resources(adapter);
+		igb_free_all_rx_resources(adapter);
+	}
+
 	igb_clear_interrupt_scheme(adapter);
 
 	pci_iounmap(pdev, adapter->io_addr);
-- 
2.14.3

^ permalink raw reply related

* Re: [PATCH iproute2 1/1] ss: remove duplicate assignment
From: Stephen Hemminger @ 2017-12-11 23:57 UTC (permalink / raw)
  To: Roman Mashak; +Cc: jhs, netdev
In-Reply-To: <1513027471-19346-1-git-send-email-mrv@mojatatu.com>

On Mon, 11 Dec 2017 16:24:31 -0500
Roman Mashak <mrv@mojatatu.com> wrote:

> Signed-off-by: Roman Mashak <mrv@mojatatu.com>


Applied and added Fixes: 8250bc9ff4e5 ("ss: Unify inet sockets output")

^ permalink raw reply

* Re: [PATCH iproute2 net-next 0/4] Abstract columns, properly space and wrap fields
From: Stephen Hemminger @ 2017-12-12  0:07 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: netdev, Sabrina Dubroca, David Ahern
In-Reply-To: <cover.1512750298.git.sbrivio@redhat.com>

On Fri,  8 Dec 2017 18:07:19 +0100
Stefano Brivio <sbrivio@redhat.com> wrote:

> Currently, 'ss' simply subdivides the whole available screen width
> between available columns, starting from a set of hardcoded amount
> of spacing and growing column widths.
> 
> This makes the output unreadable in several cases, as it doesn't take
> into account the actual content width.
> 
> Fix this by introducing a simple abstraction for columns, buffering
> the output, measuring the width of the fields, grouping fields into
> lines as they fit, equally distributing any remaining whitespace, and
> finally rendering the result. Some examples are reported below [1].
> 
> This implementation doesn't seem to cause any significant performance
> issues, as reported in 3/4.
> 
> Patch 1/4 replaces all relevant printf() calls by the out() helper,
> which simply consists of the usual printf() implementation.
> 
> Patch 2/4 implements column abstraction, with configurable column
> width and delimiters, and 3/4 splits buffering and rendering phases,
> employing a simple buffering mechanism with chunked allocation and
> introducing a rendering function.
> 
> Up to this point, the output is still unchanged.
> 
> Finally, 4/4 introduces field width calculation based on content
> length measured while buffering, in order to split fields onto
> multiple lines and equally space them within the single lines.
> 
> Now that column behaviour is well-defined and more easily
> configurable, it should be easier to further improve the output by
> splitting logically separable information (e.g. TCP details) into
> additional columns. However, this patchset keeps the full "extended"
> information into a single column, for the moment being.
> 
> 
> [1]
> 
> - 80 columns terminal, ss -Z -f netlink
>   * before:
> Recv-Q Send-Q Local Address:Port                 Peer Address:Port
> 
> 0      0            rtnl:evolution-calen/2075           *                     pr
> oc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> 0      0            rtnl:abrt-applet/32700              *                     pr
> oc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> 0      0            rtnl:firefox/21619                  *                     pr
> oc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> 0      0            rtnl:evolution-calen/32639           *                     p
> roc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> [...]
> 
>   * after:
> Recv-Q   Send-Q     Local Address:Port                      Peer Address:Port
> 0        0                   rtnl:evolution-calen/2075                  *
>  proc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> 0        0                   rtnl:abrt-applet/32700                     *
>  proc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> 0        0                   rtnl:firefox/21619                         *
>  proc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> 0        0                   rtnl:evolution-calen/32639                 *
>  proc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> [...]
> 
> - 80 colums terminal, ss -tunpl
>   * before:
> Netid  State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
> udp    UNCONN     0      0         *:37732                 *:*
> udp    UNCONN     0      0         *:5353                  *:*
> udp    UNCONN     0      0      192.168.122.1:53                    *:*
> udp    UNCONN     0      0      *%virbr0:67                    *:*
> [...]
> 
>   * after:
> Netid   State    Recv-Q   Send-Q     Local Address:Port      Peer Address:Port
> udp     UNCONN   0        0                      *:37732                *:*
> udp     UNCONN   0        0                      *:5353                 *:*
> udp     UNCONN   0        0          192.168.122.1:53                   *:*
> udp     UNCONN   0        0               *%virbr0:67                   *:*
> [...]
> 
>  - 66 columns terminal, ss -tunpl
>   * before:
> Netid  State      Recv-Q Send-Q Local Address:Port               P
> eer Address:Port
> udp    UNCONN     0      0       *:37732               *:*
> 
> udp    UNCONN     0      0       *:5353                *:*
> 
> udp    UNCONN     0      0      192.168.122.1:53
> *:*
> udp    UNCONN     0      0      *%virbr0:67                  *:*
> [...]
> 
>   * after:
> Netid State  Recv-Q Send-Q Local Address:Port   Peer Address:Port
> udp   UNCONN 0      0                  *:37732             *:*
> udp   UNCONN 0      0                  *:5353              *:*
> udp   UNCONN 0      0      192.168.122.1:53                *:*
> udp   UNCONN 0      0           *%virbr0:67                *:*
> [...]
> 
> 
> Stefano Brivio (4):
>   ss: Replace printf() calls for "main" output by calls to helper
>   ss: Introduce columns lightweight abstraction
>   ss: Buffer raw fields first, then render them as a table
>   ss: Implement automatic column width calculation

I was going to apply this but it does not apply cleanly to current iproute2 net-next
tree. Please rebase and resubmit.

^ permalink raw reply

* Re: [PATCH] Fix handling of verdicts after NF_QUEUE
From: Pablo Neira Ayuso @ 2017-12-12  0:23 UTC (permalink / raw)
  To: Debabrata Banerjee
  Cc: David S . Miller, netfilter-devel, coreteam, netdev, stable
In-Reply-To: <20171211233024.18303-1-dbanerje@akamai.com>

Hi,

Thanks for catching up this, see below.

On Mon, Dec 11, 2017 at 06:30:24PM -0500, Debabrata Banerjee wrote:
> A verdict of NF_STOLEN after NF_QUEUE will cause an incorrect return value
> and a potential kernel panic via double free of skb's
> 
> This was broken by commit 7034b566a4e7 ("netfilter: fix nf_queue handling")
> and subsequently fixed in v4.10 by commit c63cbc460419 ("netfilter:
> use switch() to handle verdict cases from nf_hook_slow()"). However that
> commit cannot be cleanly cherry-picked to v4.9
> 
> Signed-off-by: Debabrata Banerjee <dbanerje@akamai.com>
> 
> ---
> 
> This fix is only needed for v4.9 stable since v4.10+ does not have the
> issue
> ---
>  net/netfilter/core.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/net/netfilter/core.c b/net/netfilter/core.c
> index 004af030ef1a..d869ea50623e 100644
> --- a/net/netfilter/core.c
> +++ b/net/netfilter/core.c
> @@ -364,6 +364,11 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
>  		ret = nf_queue(skb, state, &entry, verdict);
>  		if (ret == 1 && entry)
>  			goto next_hook;
> +	} else {
> +		/* Implicit handling for NF_STOLEN, as well as any other
> +		 * non conventional verdicts.
> +		 */
> +		ret = 0;

Another possibility (more simple?) would be this:

int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
{
        struct nf_hook_entry *entry;
        unsigned int verdict;
-       int ret = 0;
+       int ret;

        entry = rcu_dereference(state->hook_entries);
next_hook:
+       ret = 0;

Basically, make sure ret is set to zero when jumping to the next_hook
label.

Thanks!

^ permalink raw reply

* [PATCH net-next v3 0/6] net: qualcomm: rmnet: Configuration options
From: Subash Abhinov Kasiviswanathan @ 2017-12-12  0:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan

This series adds support for configuring features on rmnet devices.
The rmnet specific features to be configured here are aggregation and
control commands.

Patch 1 is a cleanup of return codes in the transmit path.
Patch 2 removes some redundant ingress and egress macros.
Patch 3 restricts the creation of rmnet dev to one dev per mux id for a
given real dev.
Patch 4 adds ethernet data path support.
Patches 5-6 add support for configuring features on new and existing
rmnet devices.

v1->v2:
The memory leak fixed as part of patch 1 is merged seperately as
a896d94abd2c ("net: qualcomm: rmnet: Fix leak on transmit failure"). 
Fix a use after free in patch 4 if a packet with headroom lesser than ethernet
header length is received.

v2->v3: 
Fix formatting problem in patch 5 in the return statement.

Subash Abhinov Kasiviswanathan (6):
  net: qualcomm: rmnet: Remove the rmnet_map_results enum
  net: qualcomm: rmnet: Remove the some redundant macros
  net: qualcomm: rmnet: Allow only one rmnet dev per muxid per real dev
  net: qualcomm: rmnet: Process packets over ethernet
  net: qualcomm: rmnet: Allow to configure flags for new devices
  net: qualcomm: rmnet: Allow to configure flags for existing devices

 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 64 ++++++++++++++++++----
 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h |  1 -
 .../net/ethernet/qualcomm/rmnet/rmnet_handlers.c   | 42 +++++++-------
 drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h    |  9 ---
 .../net/ethernet/qualcomm/rmnet/rmnet_private.h    | 10 +---
 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c    |  3 +
 6 files changed, 78 insertions(+), 51 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH net-next v3 1/6] net: qualcomm: rmnet: Remove the rmnet_map_results enum
From: Subash Abhinov Kasiviswanathan @ 2017-12-12  0:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
In-Reply-To: <1513038615-16407-1-git-send-email-subashab@codeaurora.org>

Only the success and consumed entries were actually in use.
Use standard error codes instead.

Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
 drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 15 +++------------
 drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h      |  9 ---------
 2 files changed, 3 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
index 08e4afc..1e1ea10 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -142,11 +142,11 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
 
 	skb->protocol = htons(ETH_P_MAP);
 
-	return RMNET_MAP_SUCCESS;
+	return 0;
 
 fail:
 	kfree_skb(skb);
-	return RMNET_MAP_CONSUMED;
+	return -ENOMEM;
 }
 
 static void
@@ -213,17 +213,8 @@ void rmnet_egress_handler(struct sk_buff *skb)
 	}
 
 	if (port->egress_data_format & RMNET_EGRESS_FORMAT_MAP) {
-		switch (rmnet_map_egress_handler(skb, port, mux_id, orig_dev)) {
-		case RMNET_MAP_CONSUMED:
+		if (rmnet_map_egress_handler(skb, port, mux_id, orig_dev))
 			return;
-
-		case RMNET_MAP_SUCCESS:
-			break;
-
-		default:
-			kfree_skb(skb);
-			return;
-		}
 	}
 
 	rmnet_vnd_tx_fixup(skb, orig_dev);
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
index 3af3fe7..4df359d 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
@@ -30,15 +30,6 @@ struct rmnet_map_control_command {
 	};
 }  __aligned(1);
 
-enum rmnet_map_results {
-	RMNET_MAP_SUCCESS,
-	RMNET_MAP_CONSUMED,
-	RMNET_MAP_GENERAL_FAILURE,
-	RMNET_MAP_NOT_ENABLED,
-	RMNET_MAP_FAILED_AGGREGATION,
-	RMNET_MAP_FAILED_MUX
-};
-
 enum rmnet_map_commands {
 	RMNET_MAP_COMMAND_NONE,
 	RMNET_MAP_COMMAND_FLOW_DISABLE,
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next v3 2/6] net: qualcomm: rmnet: Remove the some redundant macros
From: Subash Abhinov Kasiviswanathan @ 2017-12-12  0:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
In-Reply-To: <1513038615-16407-1-git-send-email-subashab@codeaurora.org>

Multiplexing is always enabled when transmiting from a rmnet device,
so remove the redundant egress macros. De-multiplexing is always
enabled when receiving packets from a rmnet device, so remove those
ingress macros.

Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c   | 10 ++--------
 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h   |  1 -
 drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 19 +++++++------------
 drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h  | 10 ++--------
 4 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
index df21e90..46bb228 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -143,11 +143,7 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
 			 struct nlattr *tb[], struct nlattr *data[],
 			 struct netlink_ext_ack *extack)
 {
-	int ingress_format = RMNET_INGRESS_FORMAT_DEMUXING |
-			     RMNET_INGRESS_FORMAT_DEAGGREGATION |
-			     RMNET_INGRESS_FORMAT_MAP;
-	int egress_format = RMNET_EGRESS_FORMAT_MUXING |
-			    RMNET_EGRESS_FORMAT_MAP;
+	int ingress_format = RMNET_INGRESS_FORMAT_DEAGGREGATION;
 	struct net_device *real_dev;
 	int mode = RMNET_EPMODE_VND;
 	struct rmnet_endpoint *ep;
@@ -181,9 +177,7 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
 	if (err)
 		goto err2;
 
-	netdev_dbg(dev, "data format [ingress 0x%08X] [egress 0x%08X]\n",
-		   ingress_format, egress_format);
-	port->egress_data_format = egress_format;
+	netdev_dbg(dev, "data format [ingress 0x%08X]\n", ingress_format);
 	port->ingress_data_format = ingress_format;
 	port->rmnet_mode = mode;
 
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
index c19259e..2ea9fe3 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
@@ -33,7 +33,6 @@ struct rmnet_endpoint {
 struct rmnet_port {
 	struct net_device *dev;
 	u32 ingress_data_format;
-	u32 egress_data_format;
 	u8 nr_rmnet_devs;
 	u8 rmnet_mode;
 	struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP];
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
index 1e1ea10..a46053c 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -133,12 +133,10 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
 	if (!map_header)
 		goto fail;
 
-	if (port->egress_data_format & RMNET_EGRESS_FORMAT_MUXING) {
-		if (mux_id == 0xff)
-			map_header->mux_id = 0;
-		else
-			map_header->mux_id = mux_id;
-	}
+	if (mux_id == 0xff)
+		map_header->mux_id = 0;
+	else
+		map_header->mux_id = mux_id;
 
 	skb->protocol = htons(ETH_P_MAP);
 
@@ -178,8 +176,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
 
 	switch (port->rmnet_mode) {
 	case RMNET_EPMODE_VND:
-		if (port->ingress_data_format & RMNET_INGRESS_FORMAT_MAP)
-			rmnet_map_ingress_handler(skb, port);
+		rmnet_map_ingress_handler(skb, port);
 		break;
 	case RMNET_EPMODE_BRIDGE:
 		rmnet_bridge_handler(skb, port->bridge_ep);
@@ -212,10 +209,8 @@ void rmnet_egress_handler(struct sk_buff *skb)
 		return;
 	}
 
-	if (port->egress_data_format & RMNET_EGRESS_FORMAT_MAP) {
-		if (rmnet_map_egress_handler(skb, port, mux_id, orig_dev))
-			return;
-	}
+	if (rmnet_map_egress_handler(skb, port, mux_id, orig_dev))
+		return;
 
 	rmnet_vnd_tx_fixup(skb, orig_dev);
 
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
index 49102f9..d214280 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
@@ -19,14 +19,8 @@
 #define RMNET_TX_QUEUE_LEN         1000
 
 /* Constants */
-#define RMNET_EGRESS_FORMAT_MAP                 BIT(1)
-#define RMNET_EGRESS_FORMAT_AGGREGATION         BIT(2)
-#define RMNET_EGRESS_FORMAT_MUXING              BIT(3)
-
-#define RMNET_INGRESS_FORMAT_MAP                BIT(1)
-#define RMNET_INGRESS_FORMAT_DEAGGREGATION      BIT(2)
-#define RMNET_INGRESS_FORMAT_DEMUXING           BIT(3)
-#define RMNET_INGRESS_FORMAT_MAP_COMMANDS       BIT(4)
+#define RMNET_INGRESS_FORMAT_DEAGGREGATION      BIT(0)
+#define RMNET_INGRESS_FORMAT_MAP_COMMANDS       BIT(1)
 
 /* Replace skb->dev to a virtual rmnet device and pass up the stack */
 #define RMNET_EPMODE_VND (1)
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next v3 3/6] net: qualcomm: rmnet: Allow only one rmnet dev per muxid per real dev
From: Subash Abhinov Kasiviswanathan @ 2017-12-12  0:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
In-Reply-To: <1513038615-16407-1-git-send-email-subashab@codeaurora.org>

Upon de-multiplexing data from one real dev, the packets can be sent
to an unique rmnet device for a given mux id.

Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
index 9caa5e3..5bb29f4 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -185,6 +185,9 @@ int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,
 	if (ep->egress_dev)
 		return -EINVAL;
 
+	if (rmnet_get_endpoint(port, id))
+		return -EBUSY;
+
 	rc = register_netdevice(rmnet_dev);
 	if (!rc) {
 		ep->egress_dev = rmnet_dev;
-- 
1.9.1

^ permalink raw reply related


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