net-sysfs.c 37.9 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4
/*
 * net-sysfs.c - network device class and attributes
 *
 * Copyright (c) 2003 Stephen Hemminger <shemminger@osdl.org>
5
 *
Linus Torvalds's avatar
Linus Torvalds committed
6 7 8 9 10 11
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 */

12
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
13 14
#include <linux/kernel.h>
#include <linux/netdevice.h>
15
#include <net/switchdev.h>
Linus Torvalds's avatar
Linus Torvalds committed
16
#include <linux/if_arp.h>
17
#include <linux/slab.h>
18
#include <linux/sched/signal.h>
19
#include <linux/nsproxy.h>
Linus Torvalds's avatar
Linus Torvalds committed
20
#include <net/sock.h>
21
#include <net/net_namespace.h>
Linus Torvalds's avatar
Linus Torvalds committed
22
#include <linux/rtnetlink.h>
Tom Herbert's avatar
Tom Herbert committed
23
#include <linux/vmalloc.h>
24
#include <linux/export.h>
Tom Herbert's avatar
Tom Herbert committed
25
#include <linux/jiffies.h>
26
#include <linux/pm_runtime.h>
27
#include <linux/of.h>
28
#include <linux/of_net.h>
Linus Torvalds's avatar
Linus Torvalds committed
29

30 31
#include "net-sysfs.h"

32
#ifdef CONFIG_SYSFS
Linus Torvalds's avatar
Linus Torvalds committed
33 34 35
static const char fmt_hex[] = "%#x\n";
static const char fmt_dec[] = "%d\n";
static const char fmt_ulong[] = "%lu\n";
36
static const char fmt_u64[] = "%llu\n";
Linus Torvalds's avatar
Linus Torvalds committed
37

38
static inline int dev_isalive(const struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
39
{
40
	return dev->reg_state <= NETREG_REGISTERED;
Linus Torvalds's avatar
Linus Torvalds committed
41 42 43
}

/* use same locking rules as GIF* ioctl's */
44 45
static ssize_t netdev_show(const struct device *dev,
			   struct device_attribute *attr, char *buf,
Linus Torvalds's avatar
Linus Torvalds committed
46 47
			   ssize_t (*format)(const struct net_device *, char *))
{
48
	struct net_device *ndev = to_net_dev(dev);
Linus Torvalds's avatar
Linus Torvalds committed
49 50 51
	ssize_t ret = -EINVAL;

	read_lock(&dev_base_lock);
52 53
	if (dev_isalive(ndev))
		ret = (*format)(ndev, buf);
Linus Torvalds's avatar
Linus Torvalds committed
54 55 56 57 58 59 60
	read_unlock(&dev_base_lock);

	return ret;
}

/* generate a show function for simple field */
#define NETDEVICE_SHOW(field, format_string)				\
61
static ssize_t format_##field(const struct net_device *dev, char *buf)	\
Linus Torvalds's avatar
Linus Torvalds committed
62
{									\
63
	return sprintf(buf, format_string, dev->field);			\
Linus Torvalds's avatar
Linus Torvalds committed
64
}									\
65
static ssize_t field##_show(struct device *dev,				\
66
			    struct device_attribute *attr, char *buf)	\
Linus Torvalds's avatar
Linus Torvalds committed
67
{									\
68
	return netdev_show(dev, attr, buf, format_##field);		\
69 70 71 72 73
}									\

#define NETDEVICE_SHOW_RO(field, format_string)				\
NETDEVICE_SHOW(field, format_string);					\
static DEVICE_ATTR_RO(field)
Linus Torvalds's avatar
Linus Torvalds committed
74

75 76 77
#define NETDEVICE_SHOW_RW(field, format_string)				\
NETDEVICE_SHOW(field, format_string);					\
static DEVICE_ATTR_RW(field)
Linus Torvalds's avatar
Linus Torvalds committed
78 79

/* use same locking and permission rules as SIF* ioctl's */
80
static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
Linus Torvalds's avatar
Linus Torvalds committed
81 82 83
			    const char *buf, size_t len,
			    int (*set)(struct net_device *, unsigned long))
{
84 85
	struct net_device *netdev = to_net_dev(dev);
	struct net *net = dev_net(netdev);
Linus Torvalds's avatar
Linus Torvalds committed
86 87 88
	unsigned long new;
	int ret = -EINVAL;

89
	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds's avatar
Linus Torvalds committed
90 91
		return -EPERM;

92 93
	ret = kstrtoul(buf, 0, &new);
	if (ret)
Linus Torvalds's avatar
Linus Torvalds committed
94 95
		goto err;

96
	if (!rtnl_trylock())
97
		return restart_syscall();
98

99
	if (dev_isalive(netdev)) {
stephen hemminger's avatar
stephen hemminger committed
100 101
		ret = (*set)(netdev, new);
		if (ret == 0)
Linus Torvalds's avatar
Linus Torvalds committed
102 103 104 105 106 107 108
			ret = len;
	}
	rtnl_unlock();
 err:
	return ret;
}

109
NETDEVICE_SHOW_RO(dev_id, fmt_hex);
110
NETDEVICE_SHOW_RO(dev_port, fmt_dec);
111 112 113 114 115
NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
NETDEVICE_SHOW_RO(addr_len, fmt_dec);
NETDEVICE_SHOW_RO(ifindex, fmt_dec);
NETDEVICE_SHOW_RO(type, fmt_dec);
NETDEVICE_SHOW_RO(link_mode, fmt_dec);
Linus Torvalds's avatar
Linus Torvalds committed
116

117 118 119 120 121 122 123 124 125
static ssize_t iflink_show(struct device *dev, struct device_attribute *attr,
			   char *buf)
{
	struct net_device *ndev = to_net_dev(dev);

	return sprintf(buf, fmt_dec, dev_get_iflink(ndev));
}
static DEVICE_ATTR_RO(iflink);

126
static ssize_t format_name_assign_type(const struct net_device *dev, char *buf)
127
{
128
	return sprintf(buf, fmt_dec, dev->name_assign_type);
129 130 131 132 133 134
}

static ssize_t name_assign_type_show(struct device *dev,
				     struct device_attribute *attr,
				     char *buf)
{
135
	struct net_device *ndev = to_net_dev(dev);
136 137
	ssize_t ret = -EINVAL;

138
	if (ndev->name_assign_type != NET_NAME_UNKNOWN)
139 140 141 142 143 144
		ret = netdev_show(dev, attr, buf, format_name_assign_type);

	return ret;
}
static DEVICE_ATTR_RO(name_assign_type);

Linus Torvalds's avatar
Linus Torvalds committed
145
/* use same locking rules as GIFHWADDR ioctl's */
146
static ssize_t address_show(struct device *dev, struct device_attribute *attr,
147
			    char *buf)
Linus Torvalds's avatar
Linus Torvalds committed
148
{
149
	struct net_device *ndev = to_net_dev(dev);
Linus Torvalds's avatar
Linus Torvalds committed
150 151 152
	ssize_t ret = -EINVAL;

	read_lock(&dev_base_lock);
153 154
	if (dev_isalive(ndev))
		ret = sysfs_format_mac(buf, ndev->dev_addr, ndev->addr_len);
Linus Torvalds's avatar
Linus Torvalds committed
155 156 157
	read_unlock(&dev_base_lock);
	return ret;
}
158
static DEVICE_ATTR_RO(address);
Linus Torvalds's avatar
Linus Torvalds committed
159

160 161
static ssize_t broadcast_show(struct device *dev,
			      struct device_attribute *attr, char *buf)
Linus Torvalds's avatar
Linus Torvalds committed
162
{
163
	struct net_device *ndev = to_net_dev(dev);
stephen hemminger's avatar
stephen hemminger committed
164

165 166
	if (dev_isalive(ndev))
		return sysfs_format_mac(buf, ndev->broadcast, ndev->addr_len);
Linus Torvalds's avatar
Linus Torvalds committed
167 168
	return -EINVAL;
}
169
static DEVICE_ATTR_RO(broadcast);
Linus Torvalds's avatar
Linus Torvalds committed
170

171
static int change_carrier(struct net_device *dev, unsigned long new_carrier)
172
{
173
	if (!netif_running(dev))
174
		return -EINVAL;
stephen hemminger's avatar
stephen hemminger committed
175
	return dev_change_carrier(dev, (bool)new_carrier);
176 177
}

178 179
static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t len)
180 181 182 183
{
	return netdev_store(dev, attr, buf, len, change_carrier);
}

184
static ssize_t carrier_show(struct device *dev,
185
			    struct device_attribute *attr, char *buf)
Linus Torvalds's avatar
Linus Torvalds committed
186 187
{
	struct net_device *netdev = to_net_dev(dev);
stephen hemminger's avatar
stephen hemminger committed
188 189

	if (netif_running(netdev))
Linus Torvalds's avatar
Linus Torvalds committed
190
		return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));
stephen hemminger's avatar
stephen hemminger committed
191

Linus Torvalds's avatar
Linus Torvalds committed
192 193
	return -EINVAL;
}
194
static DEVICE_ATTR_RW(carrier);
Linus Torvalds's avatar
Linus Torvalds committed
195

196
static ssize_t speed_show(struct device *dev,
197 198 199 200 201 202 203 204
			  struct device_attribute *attr, char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
	int ret = -EINVAL;

	if (!rtnl_trylock())
		return restart_syscall();

205
	if (netif_running(netdev)) {
206 207 208 209
		struct ethtool_link_ksettings cmd;

		if (!__ethtool_get_link_ksettings(netdev, &cmd))
			ret = sprintf(buf, fmt_dec, cmd.base.speed);
210 211 212 213
	}
	rtnl_unlock();
	return ret;
}
214
static DEVICE_ATTR_RO(speed);
215

216
static ssize_t duplex_show(struct device *dev,
217 218 219 220 221 222 223 224
			   struct device_attribute *attr, char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
	int ret = -EINVAL;

	if (!rtnl_trylock())
		return restart_syscall();

225
	if (netif_running(netdev)) {
226 227 228
		struct ethtool_link_ksettings cmd;

		if (!__ethtool_get_link_ksettings(netdev, &cmd)) {
229
			const char *duplex;
230 231

			switch (cmd.base.duplex) {
232 233 234 235 236 237 238 239 240 241 242 243
			case DUPLEX_HALF:
				duplex = "half";
				break;
			case DUPLEX_FULL:
				duplex = "full";
				break;
			default:
				duplex = "unknown";
				break;
			}
			ret = sprintf(buf, "%s\n", duplex);
		}
244 245 246 247
	}
	rtnl_unlock();
	return ret;
}
248
static DEVICE_ATTR_RO(duplex);
249

250
static ssize_t dormant_show(struct device *dev,
251
			    struct device_attribute *attr, char *buf)
252 253 254 255 256 257 258 259
{
	struct net_device *netdev = to_net_dev(dev);

	if (netif_running(netdev))
		return sprintf(buf, fmt_dec, !!netif_dormant(netdev));

	return -EINVAL;
}
260
static DEVICE_ATTR_RO(dormant);
261

262
static const char *const operstates[] = {
263 264 265 266 267 268 269 270 271
	"unknown",
	"notpresent", /* currently unused */
	"down",
	"lowerlayerdown",
	"testing", /* currently unused */
	"dormant",
	"up"
};

272
static ssize_t operstate_show(struct device *dev,
273
			      struct device_attribute *attr, char *buf)
274 275 276 277 278 279 280 281 282 283
{
	const struct net_device *netdev = to_net_dev(dev);
	unsigned char operstate;

	read_lock(&dev_base_lock);
	operstate = netdev->operstate;
	if (!netif_running(netdev))
		operstate = IF_OPER_DOWN;
	read_unlock(&dev_base_lock);

284
	if (operstate >= ARRAY_SIZE(operstates))
285 286 287 288
		return -EINVAL; /* should not happen */

	return sprintf(buf, "%s\n", operstates[operstate]);
}
289
static DEVICE_ATTR_RO(operstate);
290

291 292 293 294 295
static ssize_t carrier_changes_show(struct device *dev,
				    struct device_attribute *attr,
				    char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
stephen hemminger's avatar
stephen hemminger committed
296

297 298 299 300 301
	return sprintf(buf, fmt_dec,
		       atomic_read(&netdev->carrier_changes));
}
static DEVICE_ATTR_RO(carrier_changes);

Linus Torvalds's avatar
Linus Torvalds committed
302 303
/* read-write attributes */

304
static int change_mtu(struct net_device *dev, unsigned long new_mtu)
Linus Torvalds's avatar
Linus Torvalds committed
305
{
stephen hemminger's avatar
stephen hemminger committed
306
	return dev_set_mtu(dev, (int)new_mtu);
Linus Torvalds's avatar
Linus Torvalds committed
307 308
}

309
static ssize_t mtu_store(struct device *dev, struct device_attribute *attr,
310
			 const char *buf, size_t len)
Linus Torvalds's avatar
Linus Torvalds committed
311
{
312
	return netdev_store(dev, attr, buf, len, change_mtu);
Linus Torvalds's avatar
Linus Torvalds committed
313
}
314
NETDEVICE_SHOW_RW(mtu, fmt_dec);
Linus Torvalds's avatar
Linus Torvalds committed
315

316
static int change_flags(struct net_device *dev, unsigned long new_flags)
Linus Torvalds's avatar
Linus Torvalds committed
317
{
stephen hemminger's avatar
stephen hemminger committed
318
	return dev_change_flags(dev, (unsigned int)new_flags);
Linus Torvalds's avatar
Linus Torvalds committed
319 320
}

321
static ssize_t flags_store(struct device *dev, struct device_attribute *attr,
322
			   const char *buf, size_t len)
Linus Torvalds's avatar
Linus Torvalds committed
323
{
324
	return netdev_store(dev, attr, buf, len, change_flags);
Linus Torvalds's avatar
Linus Torvalds committed
325
}
326
NETDEVICE_SHOW_RW(flags, fmt_hex);
Linus Torvalds's avatar
Linus Torvalds committed
327

328
static int change_tx_queue_len(struct net_device *dev, unsigned long new_len)
Linus Torvalds's avatar
Linus Torvalds committed
329
{
330 331 332 333 334
	unsigned int orig_len = dev->tx_queue_len;
	int res;

	if (new_len != (unsigned int)new_len)
		return -ERANGE;
335 336 337 338 339 340 341 342 343 344 345 346 347

	if (new_len != orig_len) {
		dev->tx_queue_len = new_len;
		res = call_netdevice_notifiers(NETDEV_CHANGE_TX_QUEUE_LEN, dev);
		res = notifier_to_errno(res);
		if (res) {
			netdev_err(dev,
				   "refused to change device tx_queue_len\n");
			dev->tx_queue_len = orig_len;
			return -EFAULT;
		}
	}

Linus Torvalds's avatar
Linus Torvalds committed
348 349 350
	return 0;
}

351
static ssize_t tx_queue_len_store(struct device *dev,
352 353
				  struct device_attribute *attr,
				  const char *buf, size_t len)
Linus Torvalds's avatar
Linus Torvalds committed
354
{
355 356 357
	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

358
	return netdev_store(dev, attr, buf, len, change_tx_queue_len);
Linus Torvalds's avatar
Linus Torvalds committed
359
}
360
NETDEVICE_SHOW_RW(tx_queue_len, fmt_dec);
Linus Torvalds's avatar
Linus Torvalds committed
361

362 363 364 365 366 367 368
static int change_gro_flush_timeout(struct net_device *dev, unsigned long val)
{
	dev->gro_flush_timeout = val;
	return 0;
}

static ssize_t gro_flush_timeout_store(struct device *dev,
stephen hemminger's avatar
stephen hemminger committed
369 370
				       struct device_attribute *attr,
				       const char *buf, size_t len)
371 372 373 374 375 376 377 378
{
	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	return netdev_store(dev, attr, buf, len, change_gro_flush_timeout);
}
NETDEVICE_SHOW_RW(gro_flush_timeout, fmt_ulong);

379
static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr,
380 381 382
			     const char *buf, size_t len)
{
	struct net_device *netdev = to_net_dev(dev);
383
	struct net *net = dev_net(netdev);
384
	size_t count = len;
385
	ssize_t ret = 0;
386

387
	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
388 389 390 391 392 393
		return -EPERM;

	/* ignore trailing newline */
	if (len >  0 && buf[len - 1] == '\n')
		--count;

394 395
	if (!rtnl_trylock())
		return restart_syscall();
396

397 398 399 400 401 402 403 404 405 406 407
	if (dev_isalive(netdev)) {
		ret = dev_set_alias(netdev, buf, count);
		if (ret < 0)
			goto err;
		ret = len;
		netdev_state_change(netdev);
	}
err:
	rtnl_unlock();

	return ret;
408 409
}

410
static ssize_t ifalias_show(struct device *dev,
411 412 413
			    struct device_attribute *attr, char *buf)
{
	const struct net_device *netdev = to_net_dev(dev);
414
	char tmp[IFALIASZ];
415 416
	ssize_t ret = 0;

417 418 419
	ret = dev_get_alias(netdev, tmp, sizeof(tmp));
	if (ret > 0)
		ret = sprintf(buf, "%s\n", tmp);
420 421
	return ret;
}
422
static DEVICE_ATTR_RW(ifalias);
423

424
static int change_group(struct net_device *dev, unsigned long new_group)
425
{
stephen hemminger's avatar
stephen hemminger committed
426
	dev_set_group(dev, (int)new_group);
427 428 429
	return 0;
}

430 431
static ssize_t group_store(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t len)
432 433 434
{
	return netdev_store(dev, attr, buf, len, change_group);
}
435 436 437
NETDEVICE_SHOW(group, fmt_dec);
static DEVICE_ATTR(netdev_group, S_IRUGO | S_IWUSR, group_show, group_store);

438 439
static int change_proto_down(struct net_device *dev, unsigned long proto_down)
{
stephen hemminger's avatar
stephen hemminger committed
440
	return dev_change_proto_down(dev, (bool)proto_down);
441 442 443 444 445 446 447 448 449 450
}

static ssize_t proto_down_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t len)
{
	return netdev_store(dev, attr, buf, len, change_proto_down);
}
NETDEVICE_SHOW_RW(proto_down, fmt_dec);

451
static ssize_t phys_port_id_show(struct device *dev,
452 453 454 455 456 457 458 459 460
				 struct device_attribute *attr, char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
	ssize_t ret = -EINVAL;

	if (!rtnl_trylock())
		return restart_syscall();

	if (dev_isalive(netdev)) {
461
		struct netdev_phys_item_id ppid;
462 463 464 465 466 467 468 469 470

		ret = dev_get_phys_port_id(netdev, &ppid);
		if (!ret)
			ret = sprintf(buf, "%*phN\n", ppid.id_len, ppid.id);
	}
	rtnl_unlock();

	return ret;
}
471 472
static DEVICE_ATTR_RO(phys_port_id);

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
static ssize_t phys_port_name_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
	ssize_t ret = -EINVAL;

	if (!rtnl_trylock())
		return restart_syscall();

	if (dev_isalive(netdev)) {
		char name[IFNAMSIZ];

		ret = dev_get_phys_port_name(netdev, name, sizeof(name));
		if (!ret)
			ret = sprintf(buf, "%s\n", name);
	}
	rtnl_unlock();

	return ret;
}
static DEVICE_ATTR_RO(phys_port_name);

495 496 497 498 499 500 501 502 503 504
static ssize_t phys_switch_id_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
	ssize_t ret = -EINVAL;

	if (!rtnl_trylock())
		return restart_syscall();

	if (dev_isalive(netdev)) {
505
		struct switchdev_attr attr = {
506
			.orig_dev = netdev,
507
			.id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
508 509
			.flags = SWITCHDEV_F_NO_RECURSE,
		};
510

511
		ret = switchdev_port_attr_get(netdev, &attr);
512
		if (!ret)
513 514
			ret = sprintf(buf, "%*phN\n", attr.u.ppid.id_len,
				      attr.u.ppid.id);
515 516 517 518 519 520 521
	}
	rtnl_unlock();

	return ret;
}
static DEVICE_ATTR_RO(phys_switch_id);

522
static struct attribute *net_class_attrs[] __ro_after_init = {
523 524 525
	&dev_attr_netdev_group.attr,
	&dev_attr_type.attr,
	&dev_attr_dev_id.attr,
526
	&dev_attr_dev_port.attr,
527 528
	&dev_attr_iflink.attr,
	&dev_attr_ifindex.attr,
529
	&dev_attr_name_assign_type.attr,
530 531 532 533 534 535 536 537 538
	&dev_attr_addr_assign_type.attr,
	&dev_attr_addr_len.attr,
	&dev_attr_link_mode.attr,
	&dev_attr_address.attr,
	&dev_attr_broadcast.attr,
	&dev_attr_speed.attr,
	&dev_attr_duplex.attr,
	&dev_attr_dormant.attr,
	&dev_attr_operstate.attr,
539
	&dev_attr_carrier_changes.attr,
540 541 542 543 544
	&dev_attr_ifalias.attr,
	&dev_attr_carrier.attr,
	&dev_attr_mtu.attr,
	&dev_attr_flags.attr,
	&dev_attr_tx_queue_len.attr,
545
	&dev_attr_gro_flush_timeout.attr,
546
	&dev_attr_phys_port_id.attr,
547
	&dev_attr_phys_port_name.attr,
548
	&dev_attr_phys_switch_id.attr,
549
	&dev_attr_proto_down.attr,
550
	NULL,
Linus Torvalds's avatar
Linus Torvalds committed
551
};
552
ATTRIBUTE_GROUPS(net_class);
Linus Torvalds's avatar
Linus Torvalds committed
553 554

/* Show a given an attribute in the statistics group */
555 556
static ssize_t netstat_show(const struct device *d,
			    struct device_attribute *attr, char *buf,
Linus Torvalds's avatar
Linus Torvalds committed
557 558
			    unsigned long offset)
{
559
	struct net_device *dev = to_net_dev(d);
Linus Torvalds's avatar
Linus Torvalds committed
560 561
	ssize_t ret = -EINVAL;

562
	WARN_ON(offset > sizeof(struct rtnl_link_stats64) ||
stephen hemminger's avatar
stephen hemminger committed
563
		offset % sizeof(u64) != 0);
Linus Torvalds's avatar
Linus Torvalds committed
564 565

	read_lock(&dev_base_lock);
566
	if (dev_isalive(dev)) {
567 568 569
		struct rtnl_link_stats64 temp;
		const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);

stephen hemminger's avatar
stephen hemminger committed
570
		ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *)stats) + offset));
571
	}
Linus Torvalds's avatar
Linus Torvalds committed
572 573 574 575 576 577
	read_unlock(&dev_base_lock);
	return ret;
}

/* generate a read-only statistics attribute */
#define NETSTAT_ENTRY(name)						\
578
static ssize_t name##_show(struct device *d,				\
stephen hemminger's avatar
stephen hemminger committed
579
			   struct device_attribute *attr, char *buf)	\
Linus Torvalds's avatar
Linus Torvalds committed
580
{									\
581
	return netstat_show(d, attr, buf,				\
582
			    offsetof(struct rtnl_link_stats64, name));	\
Linus Torvalds's avatar
Linus Torvalds committed
583
}									\
584
static DEVICE_ATTR_RO(name)
Linus Torvalds's avatar
Linus Torvalds committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608

NETSTAT_ENTRY(rx_packets);
NETSTAT_ENTRY(tx_packets);
NETSTAT_ENTRY(rx_bytes);
NETSTAT_ENTRY(tx_bytes);
NETSTAT_ENTRY(rx_errors);
NETSTAT_ENTRY(tx_errors);
NETSTAT_ENTRY(rx_dropped);
NETSTAT_ENTRY(tx_dropped);
NETSTAT_ENTRY(multicast);
NETSTAT_ENTRY(collisions);
NETSTAT_ENTRY(rx_length_errors);
NETSTAT_ENTRY(rx_over_errors);
NETSTAT_ENTRY(rx_crc_errors);
NETSTAT_ENTRY(rx_frame_errors);
NETSTAT_ENTRY(rx_fifo_errors);
NETSTAT_ENTRY(rx_missed_errors);
NETSTAT_ENTRY(tx_aborted_errors);
NETSTAT_ENTRY(tx_carrier_errors);
NETSTAT_ENTRY(tx_fifo_errors);
NETSTAT_ENTRY(tx_heartbeat_errors);
NETSTAT_ENTRY(tx_window_errors);
NETSTAT_ENTRY(rx_compressed);
NETSTAT_ENTRY(tx_compressed);
609
NETSTAT_ENTRY(rx_nohandler);
Linus Torvalds's avatar
Linus Torvalds committed
610

611
static struct attribute *netstat_attrs[] __ro_after_init = {
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
	&dev_attr_rx_packets.attr,
	&dev_attr_tx_packets.attr,
	&dev_attr_rx_bytes.attr,
	&dev_attr_tx_bytes.attr,
	&dev_attr_rx_errors.attr,
	&dev_attr_tx_errors.attr,
	&dev_attr_rx_dropped.attr,
	&dev_attr_tx_dropped.attr,
	&dev_attr_multicast.attr,
	&dev_attr_collisions.attr,
	&dev_attr_rx_length_errors.attr,
	&dev_attr_rx_over_errors.attr,
	&dev_attr_rx_crc_errors.attr,
	&dev_attr_rx_frame_errors.attr,
	&dev_attr_rx_fifo_errors.attr,
	&dev_attr_rx_missed_errors.attr,
	&dev_attr_tx_aborted_errors.attr,
	&dev_attr_tx_carrier_errors.attr,
	&dev_attr_tx_fifo_errors.attr,
	&dev_attr_tx_heartbeat_errors.attr,
	&dev_attr_tx_window_errors.attr,
	&dev_attr_rx_compressed.attr,
	&dev_attr_tx_compressed.attr,
635
	&dev_attr_rx_nohandler.attr,
Linus Torvalds's avatar
Linus Torvalds committed
636 637 638
	NULL
};

639
static const struct attribute_group netstat_group = {
Linus Torvalds's avatar
Linus Torvalds committed
640 641 642
	.name  = "statistics",
	.attrs  = netstat_attrs,
};
643 644 645 646 647 648

#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
static struct attribute *wireless_attrs[] = {
	NULL
};

649
static const struct attribute_group wireless_group = {
650 651 652 653
	.name = "wireless",
	.attrs = wireless_attrs,
};
#endif
654 655 656

#else /* CONFIG_SYSFS */
#define net_class_groups	NULL
657
#endif /* CONFIG_SYSFS */
Linus Torvalds's avatar
Linus Torvalds committed
658

659
#ifdef CONFIG_SYSFS
stephen hemminger's avatar
stephen hemminger committed
660 661
#define to_rx_queue_attr(_attr) \
	container_of(_attr, struct rx_queue_attribute, attr)
Tom Herbert's avatar
Tom Herbert committed
662 663 664 665 666 667

#define to_rx_queue(obj) container_of(obj, struct netdev_rx_queue, kobj)

static ssize_t rx_queue_attr_show(struct kobject *kobj, struct attribute *attr,
				  char *buf)
{
668
	const struct rx_queue_attribute *attribute = to_rx_queue_attr(attr);
Tom Herbert's avatar
Tom Herbert committed
669 670 671 672 673
	struct netdev_rx_queue *queue = to_rx_queue(kobj);

	if (!attribute->show)
		return -EIO;

674
	return attribute->show(queue, buf);
Tom Herbert's avatar
Tom Herbert committed
675 676 677 678 679
}

static ssize_t rx_queue_attr_store(struct kobject *kobj, struct attribute *attr,
				   const char *buf, size_t count)
{
680
	const struct rx_queue_attribute *attribute = to_rx_queue_attr(attr);
Tom Herbert's avatar
Tom Herbert committed
681 682 683 684 685
	struct netdev_rx_queue *queue = to_rx_queue(kobj);

	if (!attribute->store)
		return -EIO;

686
	return attribute->store(queue, buf, count);
Tom Herbert's avatar
Tom Herbert committed
687 688
}

689
static const struct sysfs_ops rx_queue_sysfs_ops = {
Tom Herbert's avatar
Tom Herbert committed
690 691 692 693
	.show = rx_queue_attr_show,
	.store = rx_queue_attr_store,
};

694
#ifdef CONFIG_RPS
695
static ssize_t show_rps_map(struct netdev_rx_queue *queue, char *buf)
Tom Herbert's avatar
Tom Herbert committed
696 697 698
{
	struct rps_map *map;
	cpumask_var_t mask;
699
	int i, len;
Tom Herbert's avatar
Tom Herbert committed
700 701 702 703 704 705 706 707 708 709

	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
		return -ENOMEM;

	rcu_read_lock();
	map = rcu_dereference(queue->rps_map);
	if (map)
		for (i = 0; i < map->len; i++)
			cpumask_set_cpu(map->cpus[i], mask);

710
	len = snprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask));
Tom Herbert's avatar
Tom Herbert committed
711 712
	rcu_read_unlock();
	free_cpumask_var(mask);
713 714

	return len < PAGE_SIZE ? len : -EINVAL;
Tom Herbert's avatar
Tom Herbert committed
715 716
}

Eric Dumazet's avatar
Eric Dumazet committed
717
static ssize_t store_rps_map(struct netdev_rx_queue *queue,
718
			     const char *buf, size_t len)
Tom Herbert's avatar
Tom Herbert committed
719 720 721 722
{
	struct rps_map *old_map, *map;
	cpumask_var_t mask;
	int err, cpu, i;
723
	static DEFINE_MUTEX(rps_map_mutex);
Tom Herbert's avatar
Tom Herbert committed
724 725 726 727 728 729 730 731 732 733 734 735 736

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
		return -ENOMEM;

	err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
	if (err) {
		free_cpumask_var(mask);
		return err;
	}

737
	map = kzalloc(max_t(unsigned int,
stephen hemminger's avatar
stephen hemminger committed
738 739
			    RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES),
		      GFP_KERNEL);
Tom Herbert's avatar
Tom Herbert committed
740 741 742 743 744 745 746 747 748
	if (!map) {
		free_cpumask_var(mask);
		return -ENOMEM;
	}

	i = 0;
	for_each_cpu_and(cpu, mask, cpu_online_mask)
		map->cpus[i++] = cpu;

stephen hemminger's avatar
stephen hemminger committed
749
	if (i) {
Tom Herbert's avatar
Tom Herbert committed
750
		map->len = i;
stephen hemminger's avatar
stephen hemminger committed
751
	} else {
Tom Herbert's avatar
Tom Herbert committed
752 753 754 755
		kfree(map);
		map = NULL;
	}

756
	mutex_lock(&rps_map_mutex);
Eric Dumazet's avatar
Eric Dumazet committed
757
	old_map = rcu_dereference_protected(queue->rps_map,
758
					    mutex_is_locked(&rps_map_mutex));
Tom Herbert's avatar
Tom Herbert committed
759 760
	rcu_assign_pointer(queue->rps_map, map);

761
	if (map)
762
		static_key_slow_inc(&rps_needed);
763
	if (old_map)
764
		static_key_slow_dec(&rps_needed);
765

766
	mutex_unlock(&rps_map_mutex);
767 768 769 770

	if (old_map)
		kfree_rcu(old_map, rcu);

Tom Herbert's avatar
Tom Herbert committed
771 772 773 774
	free_cpumask_var(mask);
	return len;
}

Tom Herbert's avatar
Tom Herbert committed
775 776 777 778
static ssize_t show_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
					   char *buf)
{
	struct rps_dev_flow_table *flow_table;
779
	unsigned long val = 0;
Tom Herbert's avatar
Tom Herbert committed
780 781 782 783

	rcu_read_lock();
	flow_table = rcu_dereference(queue->rps_flow_table);
	if (flow_table)
784
		val = (unsigned long)flow_table->mask + 1;
Tom Herbert's avatar
Tom Herbert committed
785 786
	rcu_read_unlock();

787
	return sprintf(buf, "%lu\n", val);
Tom Herbert's avatar
Tom Herbert committed
788 789 790 791 792 793
}

static void rps_dev_flow_table_release(struct rcu_head *rcu)
{
	struct rps_dev_flow_table *table = container_of(rcu,
	    struct rps_dev_flow_table, rcu);
794
	vfree(table);
Tom Herbert's avatar
Tom Herbert committed
795 796
}

Eric Dumazet's avatar
Eric Dumazet committed
797
static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
798
					    const char *buf, size_t len)
Tom Herbert's avatar
Tom Herbert committed
799
{
800
	unsigned long mask, count;
Tom Herbert's avatar
Tom Herbert committed
801 802
	struct rps_dev_flow_table *table, *old_table;
	static DEFINE_SPINLOCK(rps_dev_flow_lock);
803
	int rc;
Tom Herbert's avatar
Tom Herbert committed
804 805 806 807

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

808 809 810
	rc = kstrtoul(buf, 0, &count);
	if (rc < 0)
		return rc;
Tom Herbert's avatar
Tom Herbert committed
811 812

	if (count) {
813 814 815 816 817 818 819
		mask = count - 1;
		/* mask = roundup_pow_of_two(count) - 1;
		 * without overflows...
		 */
		while ((mask | (mask >> 1)) != mask)
			mask |= (mask >> 1);
		/* On 64 bit arches, must check mask fits in table->mask (u32),
stephen hemminger's avatar
stephen hemminger committed
820 821
		 * and on 32bit arches, must check
		 * RPS_DEV_FLOW_TABLE_SIZE(mask + 1) doesn't overflow.
822 823 824
		 */
#if BITS_PER_LONG > 32
		if (mask > (unsigned long)(u32)mask)
825
			return -EINVAL;
826 827
#else
		if (mask > (ULONG_MAX - RPS_DEV_FLOW_TABLE_SIZE(1))
828
				/ sizeof(struct rps_dev_flow)) {
Tom Herbert's avatar
Tom Herbert committed
829 830 831
			/* Enforce a limit to prevent overflow */
			return -EINVAL;
		}
832 833
#endif
		table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(mask + 1));
Tom Herbert's avatar
Tom Herbert committed
834 835 836
		if (!table)
			return -ENOMEM;

837 838 839
		table->mask = mask;
		for (count = 0; count <= mask; count++)
			table->flows[count].cpu = RPS_NO_CPU;
stephen hemminger's avatar
stephen hemminger committed
840
	} else {
Tom Herbert's avatar
Tom Herbert committed
841
		table = NULL;
stephen hemminger's avatar
stephen hemminger committed
842
	}
Tom Herbert's avatar
Tom Herbert committed
843 844

	spin_lock(&rps_dev_flow_lock);
Eric Dumazet's avatar
Eric Dumazet committed
845 846
	old_table = rcu_dereference_protected(queue->rps_flow_table,
					      lockdep_is_held(&rps_dev_flow_lock));
Tom Herbert's avatar
Tom Herbert committed
847 848 849 850 851 852 853 854 855
	rcu_assign_pointer(queue->rps_flow_table, table);
	spin_unlock(&rps_dev_flow_lock);

	if (old_table)
		call_rcu(&old_table->rcu, rps_dev_flow_table_release);

	return len;
}

856 857
static struct rx_queue_attribute rps_cpus_attribute __ro_after_init
	= __ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map);
Tom Herbert's avatar
Tom Herbert committed
858

859 860 861
static struct rx_queue_attribute rps_dev_flow_table_cnt_attribute __ro_after_init
	= __ATTR(rps_flow_cnt, S_IRUGO | S_IWUSR,
		 show_rps_dev_flow_table_cnt, store_rps_dev_flow_table_cnt);
862
#endif /* CONFIG_RPS */
Tom Herbert's avatar
Tom Herbert committed
863

864
static struct attribute *rx_queue_default_attrs[] __ro_after_init = {
865
#ifdef CONFIG_RPS
Tom Herbert's avatar
Tom Herbert committed
866
	&rps_cpus_attribute.attr,
Tom Herbert's avatar
Tom Herbert committed
867
	&rps_dev_flow_table_cnt_attribute.attr,
868
#endif
Tom Herbert's avatar
Tom Herbert committed
869 870 871 872 873 874
	NULL
};

static void rx_queue_release(struct kobject *kobj)
{
	struct netdev_rx_queue *queue = to_rx_queue(kobj);
875
#ifdef CONFIG_RPS
Eric Dumazet's avatar
Eric Dumazet committed
876 877
	struct rps_map *map;
	struct rps_dev_flow_table *flow_table;
Tom Herbert's avatar
Tom Herbert committed
878

879
	map = rcu_dereference_protected(queue->rps_map, 1);
880 881
	if (map) {
		RCU_INIT_POINTER(queue->rps_map, NULL);
882
		kfree_rcu(map, rcu);
883
	}
Eric Dumazet's avatar
Eric Dumazet committed
884

885
	flow_table = rcu_dereference_protected(queue->rps_flow_table, 1);
886 887
	if (flow_table) {
		RCU_INIT_POINTER(queue->rps_flow_table, NULL);
Eric Dumazet's avatar
Eric Dumazet committed
888
		call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
889
	}
890
#endif
Tom Herbert's avatar
Tom Herbert committed
891

892
	memset(kobj, 0, sizeof(*kobj));
893
	dev_put(queue->dev);
Tom Herbert's avatar
Tom Herbert committed
894 895
}

896 897 898 899 900 901 902 903 904 905 906 907
static const void *rx_queue_namespace(struct kobject *kobj)
{
	struct netdev_rx_queue *queue = to_rx_queue(kobj);
	struct device *dev = &queue->dev->dev;
	const void *ns = NULL;

	if (dev->class && dev->class->ns_type)
		ns = dev->class->namespace(dev);

	return ns;
}

908
static struct kobj_type rx_queue_ktype __ro_after_init = {
Tom Herbert's avatar
Tom Herbert committed
909 910 911
	.sysfs_ops = &rx_queue_sysfs_ops,
	.release = rx_queue_release,
	.default_attrs = rx_queue_default_attrs,
912
	.namespace = rx_queue_namespace
Tom Herbert's avatar
Tom Herbert committed
913 914
};

915
static int rx_queue_add_kobject(struct net_device *dev, int index)
Tom Herbert's avatar
Tom Herbert committed
916
{
917
	struct netdev_rx_queue *queue = dev->_rx + index;
Tom Herbert's avatar
Tom Herbert committed
918 919 920
	struct kobject *kobj = &queue->kobj;
	int error = 0;

921
	kobj->kset = dev->queues_kset;
Tom Herbert's avatar
Tom Herbert committed
922
	error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
stephen hemminger's avatar
stephen hemminger committed
923
				     "rx-%u", index);
924
	if (error)
925
		return error;
926

927 928
	if (dev->sysfs_rx_queue_group) {
		error = sysfs_create_group(kobj, dev->sysfs_rx_queue_group);
929 930 931 932
		if (error) {
			kobject_put(kobj);
			return error;
		}
Tom Herbert's avatar
Tom Herbert committed
933 934 935
	}

	kobject_uevent(kobj, KOBJ_ADD);
936
	dev_hold(queue->dev);
Tom Herbert's avatar
Tom Herbert committed
937 938 939

	return error;
}
940
#endif /* CONFIG_SYSFS */
Tom Herbert's avatar
Tom Herbert committed
941

942
int
943
net_rx_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
Tom Herbert's avatar
Tom Herbert committed
944
{
945
#ifdef CONFIG_SYSFS
Tom Herbert's avatar
Tom Herbert committed
946 947 948
	int i;
	int error = 0;

949
#ifndef CONFIG_RPS
950
	if (!dev->sysfs_rx_queue_group)
951 952
		return 0;
#endif
953
	for (i = old_num; i < new_num; i++) {
954
		error = rx_queue_add_kobject(dev, i);
955 956
		if (error) {
			new_num = old_num;
Tom Herbert's avatar
Tom Herbert committed
957
			break;
958
		}
Tom Herbert's avatar
Tom Herbert committed
959 960
	}

961
	while (--i >= new_num) {
962 963
		struct kobject *kobj = &dev->_rx[i].kobj;

964
		if (!atomic_read(&dev_net(dev)->count))
965
			kobj->uevent_suppress = 1;
966
		if (dev->sysfs_rx_queue_group)
967 968
			sysfs_remove_group(kobj, dev->sysfs_rx_queue_group);
		kobject_put(kobj);
969
	}
Tom Herbert's avatar
Tom Herbert committed
970 971

	return error;
Tom Herbert's avatar
Tom Herbert committed
972 973 974
#else
	return 0;
#endif
Tom Herbert's avatar
Tom Herbert committed
975 976
}

977
#ifdef CONFIG_SYSFS
Tom Herbert's avatar
Tom Herbert committed
978 979 980 981 982
/*
 * netdev_queue sysfs structures and functions.
 */
struct netdev_queue_attribute {
	struct attribute attr;
983
	ssize_t (*show)(struct netdev_queue *queue, char *buf);
Tom Herbert's avatar
Tom Herbert committed
984
	ssize_t (*store)(struct netdev_queue *queue,
985
			 const char *buf, size_t len);
Tom Herbert's avatar
Tom Herbert committed
986
};
stephen hemminger's avatar
stephen hemminger committed
987 988
#define to_netdev_queue_attr(_attr) \
	container_of(_attr, struct netdev_queue_attribute, attr)
Tom Herbert's avatar
Tom Herbert committed
989 990 991 992 993 994

#define to_netdev_queue(obj) container_of(obj, struct netdev_queue, kobj)

static ssize_t netdev_queue_attr_show(struct kobject *kobj,
				      struct attribute *attr, char *buf)
{
995 996
	const struct netdev_queue_attribute *attribute
		= to_netdev_queue_attr(attr);
Tom Herbert's avatar
Tom Herbert committed
997 998 999 1000 1001
	struct netdev_queue *queue = to_netdev_queue(kobj);

	if (!attribute->show)
		return -EIO;

1002
	return attribute->show(queue, buf);
Tom Herbert's avatar
Tom Herbert committed
1003 1004 1005 1006 1007 1008
}

static ssize_t netdev_queue_attr_store(struct kobject *kobj,
				       struct attribute *attr,
				       const char *buf, size_t count)
{
1009 1010
	const struct netdev_queue_attribute *attribute
		= to_netdev_queue_attr(attr);
Tom Herbert's avatar
Tom Herbert committed
1011 1012 1013 1014 1015
	struct netdev_queue *queue = to_netdev_queue(kobj);

	if (!attribute->store)
		return -EIO;

1016
	return attribute->store(queue, buf, count);
Tom Herbert's avatar
Tom Herbert committed
1017 1018 1019 1020 1021 1022 1023
}

static const struct sysfs_ops netdev_queue_sysfs_ops = {
	.show = netdev_queue_attr_show,
	.store = netdev_queue_attr_store,
};

1024
static ssize_t tx_timeout_show(struct netdev_queue *queue, char *buf)
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
{
	unsigned long trans_timeout;

	spin_lock_irq(&queue->_xmit_lock);
	trans_timeout = queue->trans_timeout;
	spin_unlock_irq(&queue->_xmit_lock);

	return sprintf(buf, "%lu", trans_timeout);
}

1035
static unsigned int get_netdev_queue_index(struct netdev_queue *queue)
1036 1037
{
	struct net_device *dev = queue->dev;
1038
	unsigned int i;
1039

1040
	i = queue - dev->_tx;
1041 1042 1043 1044 1045
	BUG_ON(i >= dev->num_tx_queues);

	return i;
}

1046
static ssize_t traffic_class_show(struct netdev_queue *queue,
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
				  char *buf)
{
	struct net_device *dev = queue->dev;
	int index = get_netdev_queue_index(queue);
	int tc = netdev_txq_to_tc(dev, index);

	if (tc < 0)
		return -EINVAL;

	return sprintf(buf, "%u\n", tc);
}

#ifdef CONFIG_XPS
1060
static ssize_t tx_maxrate_show(struct netdev_queue *queue,
1061 1062 1063 1064 1065
			       char *buf)
{
	return sprintf(buf, "%lu\n", queue->tx_maxrate);
}

1066 1067
static ssize_t tx_maxrate_store(struct netdev_queue *queue,
				const char *buf, size_t len)
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
{
	struct net_device *dev = queue->dev;
	int err, index = get_netdev_queue_index(queue);
	u32 rate = 0;

	err = kstrtou32(buf, 10, &rate);
	if (err < 0)
		return err;

	if (!rtnl_trylock())
		return restart_syscall();

	err = -EOPNOTSUPP;
	if (dev->netdev_ops->ndo_set_tx_maxrate)
		err = dev->netdev_ops->ndo_set_tx_maxrate(dev, index, rate);

	rtnl_unlock();
	if (!err) {
		queue->tx_maxrate = rate;
		return len;
	}
	return err;
}

1092 1093
static struct netdev_queue_attribute queue_tx_maxrate __ro_after_init
	= __ATTR_RW(tx_maxrate);
1094 1095
#endif

1096 1097
static struct netdev_queue_attribute queue_trans_timeout __ro_after_init
	= __ATTR_RO(tx_timeout);
1098

1099 1100
static struct netdev_queue_attribute queue_traffic_class __ro_after_init
	= __ATTR_RO(traffic_class);
1101

Tom Herbert's avatar
Tom Herbert committed
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
#ifdef CONFIG_BQL
/*
 * Byte queue limits sysfs structures and functions.
 */
static ssize_t bql_show(char *buf, unsigned int value)
{
	return sprintf(buf, "%u\n", value);
}

static ssize_t bql_set(const char *buf, const size_t count,
		       unsigned int *pvalue)
{
	unsigned int value;
	int err;

stephen hemminger's avatar
stephen hemminger committed
1117
	if (!strcmp(buf, "max") || !strcmp(buf, "max\n")) {
Tom Herbert's avatar
Tom Herbert committed
1118
		value = DQL_MAX_LIMIT;
stephen hemminger's avatar
stephen hemminger committed
1119
	} else {
Tom Herbert's avatar
Tom Herbert committed
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
		err = kstrtouint(buf, 10, &value);
		if (err < 0)
			return err;
		if (value > DQL_MAX_LIMIT)
			return -EINVAL;
	}

	*pvalue = value;

	return count;
}

static ssize_t bql_show_hold_time(struct netdev_queue *queue,
				  char *buf)
{
	struct dql *dql = &queue->dql;

	return sprintf(buf, "%u\n", jiffies_to_msecs(dql->slack_hold_time));
}

static ssize_t bql_set_hold_time(struct netdev_queue *queue,
				 const char *buf, size_t len)
{
	struct dql *dql = &queue->dql;
1144
	unsigned int value;
Tom Herbert's avatar
Tom Herbert committed
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
	int err;

	err = kstrtouint(buf, 10, &value);
	if (err < 0)
		return err;

	dql->slack_hold_time = msecs_to_jiffies(value);

	return len;
}

1156 1157 1158
static struct netdev_queue_attribute bql_hold_time_attribute __ro_after_init
	= __ATTR(hold_time, S_IRUGO | S_IWUSR,
		 bql_show_hold_time, bql_set_hold_time);
Tom Herbert's avatar
Tom Herbert committed
1159 1160 1161 1162 1163 1164 1165 1166 1167

static ssize_t bql_show_inflight(struct netdev_queue *queue,
				 char *buf)
{
	struct dql *dql = &queue->dql;

	return sprintf(buf, "%u\n", dql->num_queued - dql->num_completed);
}

1168
static struct netdev_queue_attribute bql_inflight_attribute __ro_after_init =
1169
	__ATTR(inflight, S_IRUGO, bql_show_inflight, NULL);
Tom Herbert's avatar
Tom Herbert committed
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183

#define BQL_ATTR(NAME, FIELD)						\
static ssize_t bql_show_ ## NAME(struct netdev_queue *queue,		\
				 char *buf)				\
{									\
	return bql_show(buf, queue->dql.FIELD);				\
}									\
									\
static ssize_t bql_set_ ## NAME(struct netdev_queue *queue,		\
				const char *buf, size_t len)		\
{									\
	return bql_set(buf, len, &queue->dql.FIELD);			\
}									\
									\
1184 1185 1186
static struct netdev_queue_attribute bql_ ## NAME ## _attribute __ro_after_init \
	= __ATTR(NAME, S_IRUGO | S_IWUSR,				\
		 bql_show_ ## NAME, bql_set_ ## NAME)
Tom Herbert's avatar
Tom Herbert committed
1187

1188 1189 1190
BQL_ATTR(limit, limit);
BQL_ATTR(limit_max, max_limit);
BQL_ATTR(limit_min, min_limit);
Tom Herbert's avatar
Tom Herbert committed
1191

1192
static struct attribute *dql_attrs[] __ro_after_init = {
Tom Herbert's avatar
Tom Herbert committed
1193 1194 1195 1196 1197 1198 1199 1200
	&bql_limit_attribute.attr,
	&bql_limit_max_attribute.attr,
	&bql_limit_min_attribute.attr,
	&bql_hold_time_attribute.attr,
	&bql_inflight_attribute.attr,
	NULL
};

1201
static const struct attribute_group dql_group = {
Tom Herbert's avatar
Tom Herbert committed
1202 1203 1204 1205 1206
	.name  = "byte_queue_limits",
	.attrs  = dql_attrs,
};
#endif /* CONFIG_BQL */

1207
#ifdef CONFIG_XPS
1208 1209
static ssize_t xps_cpus_show(struct netdev_queue *queue,
			     char *buf)
Tom Herbert's avatar
Tom Herbert committed
1210 1211
{
	struct net_device *dev = queue->dev;
1212
	int cpu, len, num_tc = 1, tc = 0;
Tom Herbert's avatar
Tom Herbert committed
1213 1214 1215 1216 1217 1218 1219 1220 1221
	struct xps_dev_maps *dev_maps;
	cpumask_var_t mask;
	unsigned long index;

	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
		return -ENOMEM;

	index = get_netdev_queue_index(queue);

1222 1223 1224 1225 1226 1227 1228
	if (dev->num_tc) {
		num_tc = dev->num_tc;
		tc = netdev_txq_to_tc(dev, index);
		if (tc < 0)
			return -EINVAL;
	}

Tom Herbert's avatar
Tom Herbert committed
1229 1230 1231
	rcu_read_lock();
	dev_maps = rcu_dereference(dev->xps_maps);
	if (dev_maps) {
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
		for_each_possible_cpu(cpu) {
			int i, tci = cpu * num_tc + tc;
			struct xps_map *map;

			map = rcu_dereference(dev_maps->cpu_map[tci]);
			if (!map)
				continue;

			for (i = map->len; i--;) {
				if (map->queues[i] == index) {
					cpumask_set_cpu(cpu, mask);
					break;
Tom Herbert's avatar
Tom Herbert committed
1244 1245 1246 1247 1248 1249
				}
			}
		}
	}
	rcu_read_unlock();

1250
	len = snprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask));
Tom Herbert's avatar
Tom Herbert committed
1251
	free_cpumask_var(mask);
1252
	return len < PAGE_SIZE ? len : -EINVAL;
Tom Herbert's avatar
Tom Herbert committed
1253 1254
}

1255 1256
static ssize_t xps_cpus_store(struct netdev_queue *queue,
			      const char *buf, size_t len)
Tom Herbert's avatar
Tom Herbert committed
1257 1258 1259
{
	struct net_device *dev = queue->dev;
	unsigned long index;
1260 1261
	cpumask_var_t mask;
	int err;
Tom Herbert's avatar
Tom Herbert committed
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
		return -ENOMEM;

	index = get_netdev_queue_index(queue);

	err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
	if (err) {
		free_cpumask_var(mask);
		return err;
	}

1277
	err = netif_set_xps_queue(dev, mask, index);
Tom Herbert's avatar
Tom Herbert committed
1278 1279 1280

	free_cpumask_var(mask);

1281
	return err ? : len;
Tom Herbert's avatar
Tom Herbert committed
1282 1283
}

1284 1285
static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init
	= __ATTR_RW(xps_cpus);
1286
#endif /* CONFIG_XPS */
Tom Herbert's avatar
Tom Herbert committed
1287

1288
static struct attribute *netdev_queue_default_attrs[] __ro_after_init = {
1289
	&queue_trans_timeout.attr,
1290
	&queue_traffic_class.attr,
1291
#ifdef CONFIG_XPS
Tom Herbert's avatar
Tom Herbert committed
1292
	&xps_cpus_attribute.attr,
1293
	&queue_tx_maxrate.attr,
1294
#endif
Tom Herbert's avatar
Tom Herbert committed
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
	NULL
};

static void netdev_queue_release(struct kobject *kobj)
{
	struct netdev_queue *queue = to_netdev_queue(kobj);

	memset(kobj, 0, sizeof(*kobj));
	dev_put(queue->dev);
}

1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
static const void *netdev_queue_namespace(struct kobject *kobj)
{
	struct netdev_queue *queue = to_netdev_queue(kobj);
	struct device *dev = &queue->dev->dev;
	const void *ns = NULL;

	if (dev->class && dev->class->ns_type)
		ns = dev->class->namespace(dev);

	return ns;
}

1318
static struct kobj_type netdev_queue_ktype __ro_after_init = {
Tom Herbert's avatar
Tom Herbert committed
1319 1320 1321
	.sysfs_ops = &netdev_queue_sysfs_ops,
	.release = netdev_queue_release,
	.default_attrs = netdev_queue_default_attrs,
1322
	.namespace = netdev_queue_namespace,
Tom Herbert's avatar
Tom Herbert committed
1323 1324
};

1325
static int netdev_queue_add_kobject(struct net_device *dev, int index)
Tom Herbert's avatar
Tom Herbert committed
1326
{
1327
	struct netdev_queue *queue = dev->_tx + index;
Tom Herbert's avatar
Tom Herbert committed
1328 1329 1330
	struct kobject *kobj = &queue->kobj;
	int error = 0;

1331
	kobj->kset = dev->queues_kset;
Tom Herbert's avatar
Tom Herbert committed
1332
	error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
stephen hemminger's avatar
stephen hemminger committed
1333
				     "tx-%u", index);
Tom Herbert's avatar
Tom Herbert committed
1334
	if (error)
1335
		return error;
Tom Herbert's avatar
Tom Herbert committed
1336 1337 1338

#ifdef CONFIG_BQL
	error = sysfs_create_group(kobj, &dql_group);
1339 1340 1341 1342
	if (error) {
		kobject_put(kobj);
		return error;
	}
Tom Herbert's avatar
Tom Herbert committed
1343
#endif
Tom Herbert's avatar
Tom Herbert committed
1344 1345 1346 1347

	kobject_uevent(kobj, KOBJ_ADD);
	dev_hold(queue->dev);

Tom Herbert's avatar
Tom Herbert committed
1348
	return 0;
Tom Herbert's avatar
Tom Herbert committed
1349
}
1350
#endif /* CONFIG_SYSFS */
Tom Herbert's avatar
Tom Herbert committed
1351 1352

int
1353
netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
Tom Herbert's avatar
Tom Herbert committed
1354
{
1355
#ifdef CONFIG_SYSFS
Tom Herbert's avatar
Tom Herbert committed
1356 1357 1358 1359
	int i;
	int error = 0;

	for (i = old_num; i < new_num; i++) {
1360
		error = netdev_queue_add_kobject(dev, i);
Tom Herbert's avatar
Tom Herbert committed
1361 1362 1363 1364 1365 1366
		if (error) {
			new_num = old_num;
			break;
		}
	}

Tom Herbert's avatar
Tom Herbert committed
1367
	while (--i >= new_num) {
1368
		struct netdev_queue *queue = dev->_tx + i;
Tom Herbert's avatar
Tom Herbert committed
1369

1370
		if (!atomic_read(&dev_net(dev)->count))
1371
			queue->kobj.uevent_suppress = 1;
Tom Herbert's avatar
Tom Herbert committed
1372 1373 1374 1375 1376
#ifdef CONFIG_BQL
		sysfs_remove_group(&queue->kobj, &dql_group);
#endif
		kobject_put(&queue->kobj);
	}
Tom Herbert's avatar
Tom Herbert committed
1377 1378

	return error;
Tom Herbert's avatar
Tom Herbert committed
1379 1380
#else
	return 0;
1381
#endif /* CONFIG_SYSFS */
Tom Herbert's avatar
Tom Herbert committed
1382 1383
}

1384
static int register_queue_kobjects(struct net_device *dev)
Tom Herbert's avatar
Tom Herbert committed
1385
{
Tom Herbert's avatar
Tom Herbert committed
1386
	int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0;
Tom Herbert's avatar
Tom Herbert committed
1387

1388
#ifdef CONFIG_SYSFS
1389
	dev->queues_kset = kset_create_and_add("queues",
stephen hemminger's avatar
stephen hemminger committed
1390
					       NULL, &dev->dev.kobj);
1391
	if (!dev->queues_kset)
1392
		return -ENOMEM;
1393
	real_rx = dev->real_num_rx_queues;
Tom Herbert's avatar
Tom Herbert committed
1394
#endif
1395
	real_tx = dev->real_num_tx_queues;
Tom Herbert's avatar
Tom Herbert committed
1396

1397
	error = net_rx_queue_update_kobjects(dev, 0, real_rx);
Tom Herbert's avatar
Tom Herbert committed
1398 1399
	if (error)
		goto error;
Tom Herbert's avatar
Tom Herbert committed
1400
	rxq = real_rx;
Tom Herbert's avatar
Tom Herbert committed
1401

1402
	error = netdev_queue_update_kobjects(dev, 0, real_tx);
Tom Herbert's avatar
Tom Herbert committed
1403 1404
	if (error)
		goto error;
Tom Herbert's avatar
Tom Herbert committed
1405
	txq = real_tx;
Tom Herbert's avatar
Tom Herbert committed
1406 1407 1408 1409

	return 0;

error:
1410 1411
	netdev_queue_update_kobjects(dev, txq, 0);
	net_rx_queue_update_kobjects(dev, rxq, 0);
Tom Herbert's avatar
Tom Herbert committed
1412
	return error;
1413
}
Tom Herbert's avatar
Tom Herbert committed
1414

1415
static void remove_queue_kobjects(struct net_device *dev)
1416
{
Tom Herbert's avatar
Tom Herbert committed
1417 1418
	int real_rx = 0, real_tx = 0;

1419
#ifdef CONFIG_SYSFS
1420
	real_rx = dev->real_num_rx_queues;
Tom Herbert's avatar
Tom Herbert committed
1421
#endif
1422
	real_tx = dev->real_num_tx_queues;
Tom Herbert's avatar
Tom Herbert committed
1423

1424 1425
	net_rx_queue_update_kobjects(dev, real_rx, 0);
	netdev_queue_update_kobjects(dev, real_tx, 0);
1426
#ifdef CONFIG_SYSFS
1427
	kset_unregister(dev->queues_kset);
Tom Herbert's avatar
Tom Herbert committed
1428
#endif
Tom Herbert's avatar
Tom Herbert committed
1429
}
1430

1431 1432 1433 1434 1435 1436 1437
static bool net_current_may_mount(void)
{
	struct net *net = current->nsproxy->net_ns;

	return ns_capable(net->user_ns, CAP_SYS_ADMIN);
}

1438
static void *net_grab_current_ns(void)
1439
{
1440 1441 1442
	struct net *ns = current->nsproxy->net_ns;
#ifdef CONFIG_NET_NS
	if (ns)
1443
		refcount_inc(&ns->passive);
1444 1445
#endif
	return ns;
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
}

static const void *net_initial_ns(void)
{
	return &init_net;
}

static const void *net_netlink_ns(struct sock *sk)
{
	return sock_net(sk);
}

1458
const struct kobj_ns_type_operations net_ns_type_operations = {
1459
	.type = KOBJ_NS_TYPE_NET,
1460
	.current_may_mount = net_current_may_mount,
1461
	.grab_current_ns = net_grab_current_ns,
1462 1463
	.netlink_ns = net_netlink_ns,
	.initial_ns = net_initial_ns,
1464
	.drop_ns = net_drop_ns,
1465
};
1466
EXPORT_SYMBOL_GPL(net_ns_type_operations);
1467

1468
static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
Linus Torvalds's avatar
Linus Torvalds committed
1469
{
1470
	struct net_device *dev = to_net_dev(d);
1471
	int retval;
Linus Torvalds's avatar
Linus Torvalds committed
1472

1473
	/* pass interface to uevent. */
1474
	retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
1475 1476
	if (retval)
		goto exit;
1477 1478 1479

	/* pass ifindex to uevent.
	 * ifindex is useful as it won't change (interface name may change)
stephen hemminger's avatar
stephen hemminger committed
1480 1481
	 * and is what RtNetlink uses natively.
	 */
1482
	retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex);
Linus Torvalds's avatar
Linus Torvalds committed
1483

1484 1485
exit:
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
1486 1487 1488
}

/*
1489
 *	netdev_release -- destroy and free a dead device.
1490
 *	Called when last reference to device kobject is gone.
Linus Torvalds's avatar
Linus Torvalds committed
1491
 */
1492
static void netdev_release(struct device *d)
Linus Torvalds's avatar
Linus Torvalds committed
1493
{
1494
	struct net_device *dev = to_net_dev(d);
Linus Torvalds's avatar
Linus Torvalds committed
1495 1496 1497

	BUG_ON(dev->reg_state != NETREG_RELEASED);

1498 1499 1500 1501
	/* no need to wait for rcu grace period:
	 * device is dead and about to be freed.
	 */
	kfree(rcu_access_pointer(dev->ifalias));
1502
	netdev_freemem(dev);
Linus Torvalds's avatar
Linus Torvalds committed
1503 1504
}

1505 1506
static const void *net_namespace(struct device *d)
{
1507 1508
	struct net_device *dev = to_net_dev(d);

1509 1510 1511
	return dev_net(dev);
}

1512
static struct class net_class __ro_after_init = {
Linus Torvalds's avatar
Linus Torvalds committed
1513
	.name = "net",
1514
	.dev_release = netdev_release,
1515
	.dev_groups = net_class_groups,
1516
	.dev_uevent = netdev_uevent,
1517 1518
	.ns_type = &net_ns_type_operations,
	.namespace = net_namespace,
Linus Torvalds's avatar
Linus Torvalds committed
1519 1520
};

1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
#ifdef CONFIG_OF_NET
static int of_dev_node_match(struct device *dev, const void *data)
{
	int ret = 0;

	if (dev->parent)
		ret = dev->parent->of_node == data;

	return ret == 0 ? dev->of_node == data : ret;
}

1532 1533 1534 1535 1536 1537 1538 1539 1540
/*
 * of_find_net_device_by_node - lookup the net device for the device node
 * @np: OF device node
 *
 * Looks up the net_device structure corresponding with the device node.
 * If successful, returns a pointer to the net_device with the embedded
 * struct device refcount incremented by one, or NULL on failure. The
 * refcount must be dropped when done with the net_device.
 */
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
struct net_device *of_find_net_device_by_node(struct device_node *np)
{
	struct device *dev;

	dev = class_find_device(&net_class, NULL, np, of_dev_node_match);
	if (!dev)
		return NULL;

	return to_net_dev(dev);
}
EXPORT_SYMBOL(of_find_net_device_by_node);
#endif

1554 1555 1556
/* Delete sysfs entries but hold kobject reference until after all
 * netdev references are gone.
 */
1557
void netdev_unregister_kobject(struct net_device *ndev)
Linus Torvalds's avatar
Linus Torvalds committed
1558
{
stephen hemminger's avatar
stephen hemminger committed
1559
	struct device *dev = &ndev->dev;
1560

1561
	if (!atomic_read(&dev_net(ndev)->count))
1562 1563
		dev_set_uevent_suppress(dev, 1);

1564
	kobject_get(&dev->kobj);
1565

1566
	remove_queue_kobjects(ndev);
Tom Herbert's avatar
Tom Herbert committed
1567

1568 1569
	pm_runtime_set_memalloc_noio(dev, false);

1570
	device_del(dev);
Linus Torvalds's avatar
Linus Torvalds committed
1571 1572 1573
}

/* Create sysfs entries for network device. */
1574
int netdev_register_kobject(struct net_device *ndev)
Linus Torvalds's avatar
Linus Torvalds committed
1575
{
stephen hemminger's avatar
stephen hemminger committed
1576
	struct device *dev = &ndev->dev;
1577
	const struct attribute_group **groups = ndev->sysfs_groups;
Tom Herbert's avatar
Tom Herbert committed
1578
	int error = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1579

1580
	device_initialize(dev);
1581
	dev->class = &net_class;
1582
	dev->platform_data = ndev;
1583
	dev->groups = groups;
Linus Torvalds's avatar
Linus Torvalds committed
1584

1585
	dev_set_name(dev, "%s", ndev->name);
Linus Torvalds's avatar
Linus Torvalds committed
1586

1587
#ifdef CONFIG_SYSFS
1588 1589 1590
	/* Allow for a device specific group */
	if (*groups)
		groups++;
Linus Torvalds's avatar
Linus Torvalds committed
1591

1592
	*groups++ = &netstat_group;
1593 1594

#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
1595
	if (ndev->ieee80211_ptr)
1596 1597
		*groups++ = &wireless_group;
#if IS_ENABLED(CONFIG_WIRELESS_EXT)
1598
	else if (ndev->wireless_handlers)
1599 1600 1601
		*groups++ = &wireless_group;
#endif
#endif
1602
#endif /* CONFIG_SYSFS */
Linus Torvalds's avatar
Linus Torvalds committed
1603

Tom Herbert's avatar
Tom Herbert committed
1604 1605 1606 1607
	error = device_add(dev);
	if (error)
		return error;

1608
	error = register_queue_kobjects(ndev);
Tom Herbert's avatar
Tom Herbert committed
1609 1610 1611 1612 1613
	if (error) {
		device_del(dev);
		return error;
	}

1614 1615
	pm_runtime_set_memalloc_noio(dev, true);

Tom Herbert's avatar
Tom Herbert committed
1616
	return error;
Linus Torvalds's avatar
Linus Torvalds committed
1617 1618
}

1619
int netdev_class_create_file_ns(const struct class_attribute *class_attr,
1620
				const void *ns)
1621
{
1622
	return class_create_file_ns(&net_class, class_attr, ns);
1623
}
1624
EXPORT_SYMBOL(netdev_class_create_file_ns);
1625

1626
void netdev_class_remove_file_ns(const struct class_attribute *class_attr,
1627
				 const void *ns)
1628
{
1629
	class_remove_file_ns(&net_class, class_attr, ns);
1630
}
1631
EXPORT_SYMBOL(netdev_class_remove_file_ns);
1632

1633
int __init netdev_kobject_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
1634
{
1635
	kobj_ns_type_register(&net_ns_type_operations);
Linus Torvalds's avatar
Linus Torvalds committed
1636 1637
	return class_register(&net_class);
}