From: Lee Jones <lee@kernel.org>
To: Marcus Flyckt <marcus.flyckt@kvaser.com>
Cc: Pavel Machek <pavel@kernel.org>,
linux-leds@vger.kernel.org, linux-kernel@vger.kernel.org,
Jimmy Assarsson <extja@kvaser.com>
Subject: Re: [PATCH v2] leds: trigger: netdev: Support devices in other network namespaces
Date: Thu, 15 Oct 2026 17:05:33 +0100 [thread overview]
Message-ID: <179198415957.839288.9912294144956773410@kernel.org> (raw)
In-Reply-To: <20261006064603.1081262-1-marcus.flyckt@kvaser.com>
On Tue, 06 Oct 2026, Marcus Flyckt wrote:
> The netdev LED trigger currently cannot resolve a network device that
> has been moved into another network namespace.
>
> For example:
>
> ip link add vm1 type veth peer vm2
> tools/leds/uledmon test:green:netdev &
>
> echo netdev > /sys/class/leds/test:green:netdev/trigger
> echo 1 > /sys/class/leds/test:green:netdev/link
>
> ip netns add ledns
> ip link set vm2 netns ledns
> ip netns exec ledns \
> sh -c 'echo vm2 > /sys/class/leds/test:green:netdev/device_name'
>
> Before this change, the lookup fails because it is always performed in
> the initial network namespace.
>
> Resolve the device name in the network namespace of the task writing
> device_name. Once resolved, follow the device through renames and
> network namespace moves.
>
> With the example above, bringing both ends up makes the LED reflect the
> link state of vm2:
>
> ip link set vm1 up
> ip netns exec ledns ip link set vm2 up
>
> A possibly confusing aspect of this change is that the feature uses the
> global LED sysfs interface, which is not network namespace aware. The
> namespace is therefore effectively selected by the task that last wrote
> device_name.
>
> Signed-off-by: Marcus Flyckt <marcus.flyckt@kvaser.com>
> Reviewed-by: Jimmy Assarsson <extja@kvaser.com>
> Tested-by: Jimmy Assarsson <extja@kvaser.com>
> ---
> Changes in v2:
> - Instead of taking a reference to a network namespace, use net_cookie
> - Include used headers explicitly
> - Use C-style comments
>
> drivers/leds/trigger/ledtrig-netdev.c | 50 +++++++++++++++++++--------
> 1 file changed, 36 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
> index 5b0132484594..16357d45b3cd 100644
> --- a/drivers/leds/trigger/ledtrig-netdev.c
> +++ b/drivers/leds/trigger/ledtrig-netdev.c
> @@ -22,10 +22,13 @@
> #include <linux/list.h>
> #include <linux/module.h>
> #include <linux/netdevice.h>
> +#include <linux/nsproxy.h>
> #include <linux/mutex.h>
> #include <linux/phy.h>
> #include <linux/rtnetlink.h>
> +#include <linux/string.h>
> #include <linux/timer.h>
> +#include <net/net_namespace.h>
> #include <net/netdev_lock.h>
> #include "../leds.h"
>
> @@ -64,6 +67,8 @@ struct led_netdev_data {
> struct led_classdev *led_cdev;
> struct net_device *net_dev;
>
> + /* net namespace cookie associated with device_name */
> + u64 net_cookie;
> char device_name[IFNAMSIZ];
> atomic_t interval;
> unsigned int last_activity;
> @@ -274,7 +279,7 @@ static ssize_t device_name_show(struct device *dev,
> }
>
> static int set_device_name(struct led_netdev_data *trigger_data,
> - const char *name, size_t size)
> + struct net *net, const char *name, size_t size)
> {
> struct net_device *new_dev = NULL;
> char device_name[IFNAMSIZ];
> @@ -294,9 +299,12 @@ static int set_device_name(struct led_netdev_data *trigger_data,
> */
> rtnl_lock();
> if (device_name[0]) {
> - new_dev = dev_get_by_name(&init_net, device_name);
> + trigger_data->net_cookie = net->net_cookie;
> + new_dev = dev_get_by_name(net, device_name);
> if (new_dev)
> netdev_lock_ops(new_dev);
> + } else {
> + trigger_data->net_cookie = 0;
> }
Should this be done under a lock?
> mutex_lock(&trigger_data->lock);
>
> @@ -331,7 +339,8 @@ static ssize_t device_name_store(struct device *dev,
> struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
> int ret;
>
> - ret = set_device_name(trigger_data, buf, size);
> + ret = set_device_name(trigger_data, current->nsproxy->net_ns, buf,
> + size);
>
> if (ret < 0)
> return ret;
> @@ -616,15 +625,24 @@ static int netdev_trig_notify(struct notifier_block *nb,
> container_of(nb, struct led_netdev_data, notifier);
> struct led_classdev *led_cdev = trigger_data->led_cdev;
>
> - if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
> - && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
> - && evt != NETDEV_CHANGENAME)
> + if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE &&
> + evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER &&
> + evt != NETDEV_CHANGENAME)
> return NOTIFY_DONE;
>
> - if (!(dev == trigger_data->net_dev ||
> - (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) ||
> - (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
> - return NOTIFY_DONE;
> + if (trigger_data->net_dev) {
> + if (dev != trigger_data->net_dev)
> + return NOTIFY_DONE;
> + /* Ignore namespace transfers */
> + if (evt == NETDEV_UNREGISTER &&
> + dev->reg_state != NETREG_UNREGISTERING)
> + return NOTIFY_DONE;
> + } else {
> + if ((evt != NETDEV_REGISTER && evt != NETDEV_CHANGENAME) ||
> + dev_net(dev)->net_cookie != trigger_data->net_cookie ||
> + strcmp(dev->name, trigger_data->device_name) != 0)
> + return NOTIFY_DONE;
> + }
>
> cancel_delayed_work_sync(&trigger_data->work);
>
> @@ -636,9 +654,12 @@ static int netdev_trig_notify(struct notifier_block *nb,
> switch (evt) {
> case NETDEV_CHANGENAME:
> case NETDEV_REGISTER:
> - dev_put(trigger_data->net_dev);
> - dev_hold(dev);
> - trigger_data->net_dev = dev;
> + if (!trigger_data->net_dev) {
> + dev_hold(dev);
> + trigger_data->net_dev = dev;
> + }
> + trigger_data->net_cookie = dev_net(dev)->net_cookie;
> + strscpy(trigger_data->device_name, dev->name, IFNAMSIZ);
> if (evt == NETDEV_CHANGENAME)
> get_device_state(trigger_data);
> break;
> @@ -765,7 +786,8 @@ static int netdev_trig_activate(struct led_classdev *led_cdev)
> const char *name = dev_name(dev);
>
> trigger_data->hw_control = true;
> - set_device_name(trigger_data, name, strlen(name));
> + set_device_name(trigger_data, dev_net(to_net_dev(dev)),
> + name, strlen(name));
>
> rc = led_cdev->hw_control_get(led_cdev, &mode);
> if (!rc)
> --
> 2.43.0
>
--
Lee Jones
prev parent reply other threads:[~2026-10-15 16:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-06 6:46 Marcus Flyckt
2026-10-15 16:05 ` Lee Jones [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=179198415957.839288.9912294144956773410@kernel.org \
--to=lee@kernel.org \
--cc=extja@kvaser.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=marcus.flyckt@kvaser.com \
--cc=pavel@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®