at v5.9 251 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * net/core/devlink.c - Network physical/parent device Netlink interface 4 * 5 * Heavily inspired by net/wireless/ 6 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 7 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 8 */ 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/types.h> 13#include <linux/slab.h> 14#include <linux/gfp.h> 15#include <linux/device.h> 16#include <linux/list.h> 17#include <linux/netdevice.h> 18#include <linux/spinlock.h> 19#include <linux/refcount.h> 20#include <linux/workqueue.h> 21#include <linux/u64_stats_sync.h> 22#include <linux/timekeeping.h> 23#include <rdma/ib_verbs.h> 24#include <net/netlink.h> 25#include <net/genetlink.h> 26#include <net/rtnetlink.h> 27#include <net/net_namespace.h> 28#include <net/sock.h> 29#include <net/devlink.h> 30#include <net/drop_monitor.h> 31#define CREATE_TRACE_POINTS 32#include <trace/events/devlink.h> 33 34static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = { 35 { 36 .name = "destination mac", 37 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, 38 .bitwidth = 48, 39 }, 40}; 41 42struct devlink_dpipe_header devlink_dpipe_header_ethernet = { 43 .name = "ethernet", 44 .id = DEVLINK_DPIPE_HEADER_ETHERNET, 45 .fields = devlink_dpipe_fields_ethernet, 46 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet), 47 .global = true, 48}; 49EXPORT_SYMBOL(devlink_dpipe_header_ethernet); 50 51static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = { 52 { 53 .name = "destination ip", 54 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP, 55 .bitwidth = 32, 56 }, 57}; 58 59struct devlink_dpipe_header devlink_dpipe_header_ipv4 = { 60 .name = "ipv4", 61 .id = DEVLINK_DPIPE_HEADER_IPV4, 62 .fields = devlink_dpipe_fields_ipv4, 63 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4), 64 .global = true, 65}; 66EXPORT_SYMBOL(devlink_dpipe_header_ipv4); 67 68static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = { 69 { 70 .name = "destination ip", 71 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP, 72 .bitwidth = 128, 73 }, 74}; 75 76struct devlink_dpipe_header devlink_dpipe_header_ipv6 = { 77 .name = "ipv6", 78 .id = DEVLINK_DPIPE_HEADER_IPV6, 79 .fields = devlink_dpipe_fields_ipv6, 80 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6), 81 .global = true, 82}; 83EXPORT_SYMBOL(devlink_dpipe_header_ipv6); 84 85EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg); 86EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr); 87 88static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = { 89 [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY }, 90}; 91 92static LIST_HEAD(devlink_list); 93 94/* devlink_mutex 95 * 96 * An overall lock guarding every operation coming from userspace. 97 * It also guards devlink devices list and it is taken when 98 * driver registers/unregisters it. 99 */ 100static DEFINE_MUTEX(devlink_mutex); 101 102struct net *devlink_net(const struct devlink *devlink) 103{ 104 return read_pnet(&devlink->_net); 105} 106EXPORT_SYMBOL_GPL(devlink_net); 107 108static void __devlink_net_set(struct devlink *devlink, struct net *net) 109{ 110 write_pnet(&devlink->_net, net); 111} 112 113void devlink_net_set(struct devlink *devlink, struct net *net) 114{ 115 if (WARN_ON(devlink->registered)) 116 return; 117 __devlink_net_set(devlink, net); 118} 119EXPORT_SYMBOL_GPL(devlink_net_set); 120 121static struct devlink *devlink_get_from_attrs(struct net *net, 122 struct nlattr **attrs) 123{ 124 struct devlink *devlink; 125 char *busname; 126 char *devname; 127 128 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME]) 129 return ERR_PTR(-EINVAL); 130 131 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); 132 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); 133 134 lockdep_assert_held(&devlink_mutex); 135 136 list_for_each_entry(devlink, &devlink_list, list) { 137 if (strcmp(devlink->dev->bus->name, busname) == 0 && 138 strcmp(dev_name(devlink->dev), devname) == 0 && 139 net_eq(devlink_net(devlink), net)) 140 return devlink; 141 } 142 143 return ERR_PTR(-ENODEV); 144} 145 146static struct devlink *devlink_get_from_info(struct genl_info *info) 147{ 148 return devlink_get_from_attrs(genl_info_net(info), info->attrs); 149} 150 151static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 152 unsigned int port_index) 153{ 154 struct devlink_port *devlink_port; 155 156 list_for_each_entry(devlink_port, &devlink->port_list, list) { 157 if (devlink_port->index == port_index) 158 return devlink_port; 159 } 160 return NULL; 161} 162 163static bool devlink_port_index_exists(struct devlink *devlink, 164 unsigned int port_index) 165{ 166 return devlink_port_get_by_index(devlink, port_index); 167} 168 169static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 170 struct nlattr **attrs) 171{ 172 if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 173 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 174 struct devlink_port *devlink_port; 175 176 devlink_port = devlink_port_get_by_index(devlink, port_index); 177 if (!devlink_port) 178 return ERR_PTR(-ENODEV); 179 return devlink_port; 180 } 181 return ERR_PTR(-EINVAL); 182} 183 184static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 185 struct genl_info *info) 186{ 187 return devlink_port_get_from_attrs(devlink, info->attrs); 188} 189 190struct devlink_sb { 191 struct list_head list; 192 unsigned int index; 193 u32 size; 194 u16 ingress_pools_count; 195 u16 egress_pools_count; 196 u16 ingress_tc_count; 197 u16 egress_tc_count; 198}; 199 200static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 201{ 202 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 203} 204 205static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 206 unsigned int sb_index) 207{ 208 struct devlink_sb *devlink_sb; 209 210 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 211 if (devlink_sb->index == sb_index) 212 return devlink_sb; 213 } 214 return NULL; 215} 216 217static bool devlink_sb_index_exists(struct devlink *devlink, 218 unsigned int sb_index) 219{ 220 return devlink_sb_get_by_index(devlink, sb_index); 221} 222 223static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 224 struct nlattr **attrs) 225{ 226 if (attrs[DEVLINK_ATTR_SB_INDEX]) { 227 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 228 struct devlink_sb *devlink_sb; 229 230 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 231 if (!devlink_sb) 232 return ERR_PTR(-ENODEV); 233 return devlink_sb; 234 } 235 return ERR_PTR(-EINVAL); 236} 237 238static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 239 struct genl_info *info) 240{ 241 return devlink_sb_get_from_attrs(devlink, info->attrs); 242} 243 244static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 245 struct nlattr **attrs, 246 u16 *p_pool_index) 247{ 248 u16 val; 249 250 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 251 return -EINVAL; 252 253 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 254 if (val >= devlink_sb_pool_count(devlink_sb)) 255 return -EINVAL; 256 *p_pool_index = val; 257 return 0; 258} 259 260static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 261 struct genl_info *info, 262 u16 *p_pool_index) 263{ 264 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 265 p_pool_index); 266} 267 268static int 269devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 270 enum devlink_sb_pool_type *p_pool_type) 271{ 272 u8 val; 273 274 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 275 return -EINVAL; 276 277 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 278 if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 279 val != DEVLINK_SB_POOL_TYPE_EGRESS) 280 return -EINVAL; 281 *p_pool_type = val; 282 return 0; 283} 284 285static int 286devlink_sb_pool_type_get_from_info(struct genl_info *info, 287 enum devlink_sb_pool_type *p_pool_type) 288{ 289 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 290} 291 292static int 293devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 294 enum devlink_sb_threshold_type *p_th_type) 295{ 296 u8 val; 297 298 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 299 return -EINVAL; 300 301 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 302 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 303 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 304 return -EINVAL; 305 *p_th_type = val; 306 return 0; 307} 308 309static int 310devlink_sb_th_type_get_from_info(struct genl_info *info, 311 enum devlink_sb_threshold_type *p_th_type) 312{ 313 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 314} 315 316static int 317devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 318 struct nlattr **attrs, 319 enum devlink_sb_pool_type pool_type, 320 u16 *p_tc_index) 321{ 322 u16 val; 323 324 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 325 return -EINVAL; 326 327 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 328 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 329 val >= devlink_sb->ingress_tc_count) 330 return -EINVAL; 331 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 332 val >= devlink_sb->egress_tc_count) 333 return -EINVAL; 334 *p_tc_index = val; 335 return 0; 336} 337 338static int 339devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 340 struct genl_info *info, 341 enum devlink_sb_pool_type pool_type, 342 u16 *p_tc_index) 343{ 344 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 345 pool_type, p_tc_index); 346} 347 348struct devlink_region { 349 struct devlink *devlink; 350 struct list_head list; 351 const struct devlink_region_ops *ops; 352 struct list_head snapshot_list; 353 u32 max_snapshots; 354 u32 cur_snapshots; 355 u64 size; 356}; 357 358struct devlink_snapshot { 359 struct list_head list; 360 struct devlink_region *region; 361 u8 *data; 362 u32 id; 363}; 364 365static struct devlink_region * 366devlink_region_get_by_name(struct devlink *devlink, const char *region_name) 367{ 368 struct devlink_region *region; 369 370 list_for_each_entry(region, &devlink->region_list, list) 371 if (!strcmp(region->ops->name, region_name)) 372 return region; 373 374 return NULL; 375} 376 377static struct devlink_snapshot * 378devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) 379{ 380 struct devlink_snapshot *snapshot; 381 382 list_for_each_entry(snapshot, &region->snapshot_list, list) 383 if (snapshot->id == id) 384 return snapshot; 385 386 return NULL; 387} 388 389#define DEVLINK_NL_FLAG_NEED_PORT BIT(0) 390#define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(1) 391 392/* The per devlink instance lock is taken by default in the pre-doit 393 * operation, yet several commands do not require this. The global 394 * devlink lock is taken and protects from disruption by user-calls. 395 */ 396#define DEVLINK_NL_FLAG_NO_LOCK BIT(2) 397 398static int devlink_nl_pre_doit(const struct genl_ops *ops, 399 struct sk_buff *skb, struct genl_info *info) 400{ 401 struct devlink_port *devlink_port; 402 struct devlink *devlink; 403 int err; 404 405 mutex_lock(&devlink_mutex); 406 devlink = devlink_get_from_info(info); 407 if (IS_ERR(devlink)) { 408 mutex_unlock(&devlink_mutex); 409 return PTR_ERR(devlink); 410 } 411 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 412 mutex_lock(&devlink->lock); 413 info->user_ptr[0] = devlink; 414 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { 415 devlink_port = devlink_port_get_from_info(devlink, info); 416 if (IS_ERR(devlink_port)) { 417 err = PTR_ERR(devlink_port); 418 goto unlock; 419 } 420 info->user_ptr[1] = devlink_port; 421 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT) { 422 devlink_port = devlink_port_get_from_info(devlink, info); 423 if (!IS_ERR(devlink_port)) 424 info->user_ptr[1] = devlink_port; 425 } 426 return 0; 427 428unlock: 429 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 430 mutex_unlock(&devlink->lock); 431 mutex_unlock(&devlink_mutex); 432 return err; 433} 434 435static void devlink_nl_post_doit(const struct genl_ops *ops, 436 struct sk_buff *skb, struct genl_info *info) 437{ 438 struct devlink *devlink; 439 440 devlink = info->user_ptr[0]; 441 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 442 mutex_unlock(&devlink->lock); 443 mutex_unlock(&devlink_mutex); 444} 445 446static struct genl_family devlink_nl_family; 447 448enum devlink_multicast_groups { 449 DEVLINK_MCGRP_CONFIG, 450}; 451 452static const struct genl_multicast_group devlink_nl_mcgrps[] = { 453 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, 454}; 455 456static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink) 457{ 458 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name)) 459 return -EMSGSIZE; 460 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 461 return -EMSGSIZE; 462 return 0; 463} 464 465static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, 466 enum devlink_command cmd, u32 portid, 467 u32 seq, int flags) 468{ 469 void *hdr; 470 471 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 472 if (!hdr) 473 return -EMSGSIZE; 474 475 if (devlink_nl_put_handle(msg, devlink)) 476 goto nla_put_failure; 477 if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed)) 478 goto nla_put_failure; 479 480 genlmsg_end(msg, hdr); 481 return 0; 482 483nla_put_failure: 484 genlmsg_cancel(msg, hdr); 485 return -EMSGSIZE; 486} 487 488static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 489{ 490 struct sk_buff *msg; 491 int err; 492 493 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL); 494 495 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 496 if (!msg) 497 return; 498 499 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0); 500 if (err) { 501 nlmsg_free(msg); 502 return; 503 } 504 505 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 506 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 507} 508 509static int devlink_nl_port_attrs_put(struct sk_buff *msg, 510 struct devlink_port *devlink_port) 511{ 512 struct devlink_port_attrs *attrs = &devlink_port->attrs; 513 514 if (!devlink_port->attrs_set) 515 return 0; 516 if (attrs->lanes) { 517 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_LANES, attrs->lanes)) 518 return -EMSGSIZE; 519 } 520 if (nla_put_u8(msg, DEVLINK_ATTR_PORT_SPLITTABLE, attrs->splittable)) 521 return -EMSGSIZE; 522 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 523 return -EMSGSIZE; 524 switch (devlink_port->attrs.flavour) { 525 case DEVLINK_PORT_FLAVOUR_PCI_PF: 526 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, 527 attrs->pci_pf.pf)) 528 return -EMSGSIZE; 529 break; 530 case DEVLINK_PORT_FLAVOUR_PCI_VF: 531 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, 532 attrs->pci_vf.pf) || 533 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER, 534 attrs->pci_vf.vf)) 535 return -EMSGSIZE; 536 break; 537 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 538 case DEVLINK_PORT_FLAVOUR_CPU: 539 case DEVLINK_PORT_FLAVOUR_DSA: 540 case DEVLINK_PORT_FLAVOUR_VIRTUAL: 541 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, 542 attrs->phys.port_number)) 543 return -EMSGSIZE; 544 if (!attrs->split) 545 return 0; 546 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, 547 attrs->phys.port_number)) 548 return -EMSGSIZE; 549 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 550 attrs->phys.split_subport_number)) 551 return -EMSGSIZE; 552 break; 553 default: 554 break; 555 } 556 return 0; 557} 558 559static int 560devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *port, 561 struct netlink_ext_ack *extack) 562{ 563 struct devlink *devlink = port->devlink; 564 const struct devlink_ops *ops; 565 struct nlattr *function_attr; 566 bool empty_nest = true; 567 int err = 0; 568 569 function_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PORT_FUNCTION); 570 if (!function_attr) 571 return -EMSGSIZE; 572 573 ops = devlink->ops; 574 if (ops->port_function_hw_addr_get) { 575 int hw_addr_len; 576 u8 hw_addr[MAX_ADDR_LEN]; 577 578 err = ops->port_function_hw_addr_get(devlink, port, hw_addr, &hw_addr_len, extack); 579 if (err == -EOPNOTSUPP) { 580 /* Port function attributes are optional for a port. If port doesn't 581 * support function attribute, returning -EOPNOTSUPP is not an error. 582 */ 583 err = 0; 584 goto out; 585 } else if (err) { 586 goto out; 587 } 588 err = nla_put(msg, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, hw_addr_len, hw_addr); 589 if (err) 590 goto out; 591 empty_nest = false; 592 } 593 594out: 595 if (err || empty_nest) 596 nla_nest_cancel(msg, function_attr); 597 else 598 nla_nest_end(msg, function_attr); 599 return err; 600} 601 602static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, 603 struct devlink_port *devlink_port, 604 enum devlink_command cmd, u32 portid, 605 u32 seq, int flags, 606 struct netlink_ext_ack *extack) 607{ 608 void *hdr; 609 610 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 611 if (!hdr) 612 return -EMSGSIZE; 613 614 if (devlink_nl_put_handle(msg, devlink)) 615 goto nla_put_failure; 616 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 617 goto nla_put_failure; 618 619 spin_lock_bh(&devlink_port->type_lock); 620 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 621 goto nla_put_failure_type_locked; 622 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 623 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 624 devlink_port->desired_type)) 625 goto nla_put_failure_type_locked; 626 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 627 struct net_device *netdev = devlink_port->type_dev; 628 629 if (netdev && 630 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 631 netdev->ifindex) || 632 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 633 netdev->name))) 634 goto nla_put_failure_type_locked; 635 } 636 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 637 struct ib_device *ibdev = devlink_port->type_dev; 638 639 if (ibdev && 640 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 641 ibdev->name)) 642 goto nla_put_failure_type_locked; 643 } 644 spin_unlock_bh(&devlink_port->type_lock); 645 if (devlink_nl_port_attrs_put(msg, devlink_port)) 646 goto nla_put_failure; 647 if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack)) 648 goto nla_put_failure; 649 650 genlmsg_end(msg, hdr); 651 return 0; 652 653nla_put_failure_type_locked: 654 spin_unlock_bh(&devlink_port->type_lock); 655nla_put_failure: 656 genlmsg_cancel(msg, hdr); 657 return -EMSGSIZE; 658} 659 660static void devlink_port_notify(struct devlink_port *devlink_port, 661 enum devlink_command cmd) 662{ 663 struct devlink *devlink = devlink_port->devlink; 664 struct sk_buff *msg; 665 int err; 666 667 if (!devlink_port->registered) 668 return; 669 670 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 671 672 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 673 if (!msg) 674 return; 675 676 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0, 677 NULL); 678 if (err) { 679 nlmsg_free(msg); 680 return; 681 } 682 683 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 684 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 685} 686 687static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info) 688{ 689 struct devlink *devlink = info->user_ptr[0]; 690 struct sk_buff *msg; 691 int err; 692 693 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 694 if (!msg) 695 return -ENOMEM; 696 697 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 698 info->snd_portid, info->snd_seq, 0); 699 if (err) { 700 nlmsg_free(msg); 701 return err; 702 } 703 704 return genlmsg_reply(msg, info); 705} 706 707static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, 708 struct netlink_callback *cb) 709{ 710 struct devlink *devlink; 711 int start = cb->args[0]; 712 int idx = 0; 713 int err; 714 715 mutex_lock(&devlink_mutex); 716 list_for_each_entry(devlink, &devlink_list, list) { 717 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 718 continue; 719 if (idx < start) { 720 idx++; 721 continue; 722 } 723 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 724 NETLINK_CB(cb->skb).portid, 725 cb->nlh->nlmsg_seq, NLM_F_MULTI); 726 if (err) 727 goto out; 728 idx++; 729 } 730out: 731 mutex_unlock(&devlink_mutex); 732 733 cb->args[0] = idx; 734 return msg->len; 735} 736 737static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, 738 struct genl_info *info) 739{ 740 struct devlink_port *devlink_port = info->user_ptr[1]; 741 struct devlink *devlink = devlink_port->devlink; 742 struct sk_buff *msg; 743 int err; 744 745 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 746 if (!msg) 747 return -ENOMEM; 748 749 err = devlink_nl_port_fill(msg, devlink, devlink_port, 750 DEVLINK_CMD_PORT_NEW, 751 info->snd_portid, info->snd_seq, 0, 752 info->extack); 753 if (err) { 754 nlmsg_free(msg); 755 return err; 756 } 757 758 return genlmsg_reply(msg, info); 759} 760 761static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, 762 struct netlink_callback *cb) 763{ 764 struct devlink *devlink; 765 struct devlink_port *devlink_port; 766 int start = cb->args[0]; 767 int idx = 0; 768 int err; 769 770 mutex_lock(&devlink_mutex); 771 list_for_each_entry(devlink, &devlink_list, list) { 772 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 773 continue; 774 mutex_lock(&devlink->lock); 775 list_for_each_entry(devlink_port, &devlink->port_list, list) { 776 if (idx < start) { 777 idx++; 778 continue; 779 } 780 err = devlink_nl_port_fill(msg, devlink, devlink_port, 781 DEVLINK_CMD_NEW, 782 NETLINK_CB(cb->skb).portid, 783 cb->nlh->nlmsg_seq, 784 NLM_F_MULTI, 785 cb->extack); 786 if (err) { 787 mutex_unlock(&devlink->lock); 788 goto out; 789 } 790 idx++; 791 } 792 mutex_unlock(&devlink->lock); 793 } 794out: 795 mutex_unlock(&devlink_mutex); 796 797 cb->args[0] = idx; 798 return msg->len; 799} 800 801static int devlink_port_type_set(struct devlink *devlink, 802 struct devlink_port *devlink_port, 803 enum devlink_port_type port_type) 804 805{ 806 int err; 807 808 if (devlink->ops->port_type_set) { 809 if (port_type == DEVLINK_PORT_TYPE_NOTSET) 810 return -EINVAL; 811 if (port_type == devlink_port->type) 812 return 0; 813 err = devlink->ops->port_type_set(devlink_port, port_type); 814 if (err) 815 return err; 816 devlink_port->desired_type = port_type; 817 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 818 return 0; 819 } 820 return -EOPNOTSUPP; 821} 822 823static int 824devlink_port_function_hw_addr_set(struct devlink *devlink, struct devlink_port *port, 825 const struct nlattr *attr, struct netlink_ext_ack *extack) 826{ 827 const struct devlink_ops *ops; 828 const u8 *hw_addr; 829 int hw_addr_len; 830 int err; 831 832 hw_addr = nla_data(attr); 833 hw_addr_len = nla_len(attr); 834 if (hw_addr_len > MAX_ADDR_LEN) { 835 NL_SET_ERR_MSG_MOD(extack, "Port function hardware address too long"); 836 return -EINVAL; 837 } 838 if (port->type == DEVLINK_PORT_TYPE_ETH) { 839 if (hw_addr_len != ETH_ALEN) { 840 NL_SET_ERR_MSG_MOD(extack, "Address must be 6 bytes for Ethernet device"); 841 return -EINVAL; 842 } 843 if (!is_unicast_ether_addr(hw_addr)) { 844 NL_SET_ERR_MSG_MOD(extack, "Non-unicast hardware address unsupported"); 845 return -EINVAL; 846 } 847 } 848 849 ops = devlink->ops; 850 if (!ops->port_function_hw_addr_set) { 851 NL_SET_ERR_MSG_MOD(extack, "Port doesn't support function attributes"); 852 return -EOPNOTSUPP; 853 } 854 855 err = ops->port_function_hw_addr_set(devlink, port, hw_addr, hw_addr_len, extack); 856 if (err) 857 return err; 858 859 devlink_port_notify(port, DEVLINK_CMD_PORT_NEW); 860 return 0; 861} 862 863static int 864devlink_port_function_set(struct devlink *devlink, struct devlink_port *port, 865 const struct nlattr *attr, struct netlink_ext_ack *extack) 866{ 867 struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1]; 868 int err; 869 870 err = nla_parse_nested(tb, DEVLINK_PORT_FUNCTION_ATTR_MAX, attr, 871 devlink_function_nl_policy, extack); 872 if (err < 0) { 873 NL_SET_ERR_MSG_MOD(extack, "Fail to parse port function attributes"); 874 return err; 875 } 876 877 attr = tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]; 878 if (attr) 879 err = devlink_port_function_hw_addr_set(devlink, port, attr, extack); 880 881 return err; 882} 883 884static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 885 struct genl_info *info) 886{ 887 struct devlink_port *devlink_port = info->user_ptr[1]; 888 struct devlink *devlink = devlink_port->devlink; 889 int err; 890 891 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 892 enum devlink_port_type port_type; 893 894 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 895 err = devlink_port_type_set(devlink, devlink_port, port_type); 896 if (err) 897 return err; 898 } 899 900 if (info->attrs[DEVLINK_ATTR_PORT_FUNCTION]) { 901 struct nlattr *attr = info->attrs[DEVLINK_ATTR_PORT_FUNCTION]; 902 struct netlink_ext_ack *extack = info->extack; 903 904 err = devlink_port_function_set(devlink, devlink_port, attr, extack); 905 if (err) 906 return err; 907 } 908 909 return 0; 910} 911 912static int devlink_port_split(struct devlink *devlink, u32 port_index, 913 u32 count, struct netlink_ext_ack *extack) 914 915{ 916 if (devlink->ops->port_split) 917 return devlink->ops->port_split(devlink, port_index, count, 918 extack); 919 return -EOPNOTSUPP; 920} 921 922static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 923 struct genl_info *info) 924{ 925 struct devlink *devlink = info->user_ptr[0]; 926 struct devlink_port *devlink_port; 927 u32 port_index; 928 u32 count; 929 930 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] || 931 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]) 932 return -EINVAL; 933 934 devlink_port = devlink_port_get_from_info(devlink, info); 935 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 936 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 937 938 if (IS_ERR(devlink_port)) 939 return -EINVAL; 940 941 if (!devlink_port->attrs.splittable) { 942 /* Split ports cannot be split. */ 943 if (devlink_port->attrs.split) 944 NL_SET_ERR_MSG_MOD(info->extack, "Port cannot be split further"); 945 else 946 NL_SET_ERR_MSG_MOD(info->extack, "Port cannot be split"); 947 return -EINVAL; 948 } 949 950 if (count < 2 || !is_power_of_2(count) || count > devlink_port->attrs.lanes) { 951 NL_SET_ERR_MSG_MOD(info->extack, "Invalid split count"); 952 return -EINVAL; 953 } 954 955 return devlink_port_split(devlink, port_index, count, info->extack); 956} 957 958static int devlink_port_unsplit(struct devlink *devlink, u32 port_index, 959 struct netlink_ext_ack *extack) 960 961{ 962 if (devlink->ops->port_unsplit) 963 return devlink->ops->port_unsplit(devlink, port_index, extack); 964 return -EOPNOTSUPP; 965} 966 967static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 968 struct genl_info *info) 969{ 970 struct devlink *devlink = info->user_ptr[0]; 971 u32 port_index; 972 973 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) 974 return -EINVAL; 975 976 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 977 return devlink_port_unsplit(devlink, port_index, info->extack); 978} 979 980static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 981 struct devlink_sb *devlink_sb, 982 enum devlink_command cmd, u32 portid, 983 u32 seq, int flags) 984{ 985 void *hdr; 986 987 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 988 if (!hdr) 989 return -EMSGSIZE; 990 991 if (devlink_nl_put_handle(msg, devlink)) 992 goto nla_put_failure; 993 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 994 goto nla_put_failure; 995 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 996 goto nla_put_failure; 997 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 998 devlink_sb->ingress_pools_count)) 999 goto nla_put_failure; 1000 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 1001 devlink_sb->egress_pools_count)) 1002 goto nla_put_failure; 1003 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 1004 devlink_sb->ingress_tc_count)) 1005 goto nla_put_failure; 1006 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 1007 devlink_sb->egress_tc_count)) 1008 goto nla_put_failure; 1009 1010 genlmsg_end(msg, hdr); 1011 return 0; 1012 1013nla_put_failure: 1014 genlmsg_cancel(msg, hdr); 1015 return -EMSGSIZE; 1016} 1017 1018static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, 1019 struct genl_info *info) 1020{ 1021 struct devlink *devlink = info->user_ptr[0]; 1022 struct devlink_sb *devlink_sb; 1023 struct sk_buff *msg; 1024 int err; 1025 1026 devlink_sb = devlink_sb_get_from_info(devlink, info); 1027 if (IS_ERR(devlink_sb)) 1028 return PTR_ERR(devlink_sb); 1029 1030 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1031 if (!msg) 1032 return -ENOMEM; 1033 1034 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 1035 DEVLINK_CMD_SB_NEW, 1036 info->snd_portid, info->snd_seq, 0); 1037 if (err) { 1038 nlmsg_free(msg); 1039 return err; 1040 } 1041 1042 return genlmsg_reply(msg, info); 1043} 1044 1045static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, 1046 struct netlink_callback *cb) 1047{ 1048 struct devlink *devlink; 1049 struct devlink_sb *devlink_sb; 1050 int start = cb->args[0]; 1051 int idx = 0; 1052 int err; 1053 1054 mutex_lock(&devlink_mutex); 1055 list_for_each_entry(devlink, &devlink_list, list) { 1056 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 1057 continue; 1058 mutex_lock(&devlink->lock); 1059 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1060 if (idx < start) { 1061 idx++; 1062 continue; 1063 } 1064 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 1065 DEVLINK_CMD_SB_NEW, 1066 NETLINK_CB(cb->skb).portid, 1067 cb->nlh->nlmsg_seq, 1068 NLM_F_MULTI); 1069 if (err) { 1070 mutex_unlock(&devlink->lock); 1071 goto out; 1072 } 1073 idx++; 1074 } 1075 mutex_unlock(&devlink->lock); 1076 } 1077out: 1078 mutex_unlock(&devlink_mutex); 1079 1080 cb->args[0] = idx; 1081 return msg->len; 1082} 1083 1084static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 1085 struct devlink_sb *devlink_sb, 1086 u16 pool_index, enum devlink_command cmd, 1087 u32 portid, u32 seq, int flags) 1088{ 1089 struct devlink_sb_pool_info pool_info; 1090 void *hdr; 1091 int err; 1092 1093 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 1094 pool_index, &pool_info); 1095 if (err) 1096 return err; 1097 1098 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1099 if (!hdr) 1100 return -EMSGSIZE; 1101 1102 if (devlink_nl_put_handle(msg, devlink)) 1103 goto nla_put_failure; 1104 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1105 goto nla_put_failure; 1106 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1107 goto nla_put_failure; 1108 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 1109 goto nla_put_failure; 1110 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 1111 goto nla_put_failure; 1112 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 1113 pool_info.threshold_type)) 1114 goto nla_put_failure; 1115 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE, 1116 pool_info.cell_size)) 1117 goto nla_put_failure; 1118 1119 genlmsg_end(msg, hdr); 1120 return 0; 1121 1122nla_put_failure: 1123 genlmsg_cancel(msg, hdr); 1124 return -EMSGSIZE; 1125} 1126 1127static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, 1128 struct genl_info *info) 1129{ 1130 struct devlink *devlink = info->user_ptr[0]; 1131 struct devlink_sb *devlink_sb; 1132 struct sk_buff *msg; 1133 u16 pool_index; 1134 int err; 1135 1136 devlink_sb = devlink_sb_get_from_info(devlink, info); 1137 if (IS_ERR(devlink_sb)) 1138 return PTR_ERR(devlink_sb); 1139 1140 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1141 &pool_index); 1142 if (err) 1143 return err; 1144 1145 if (!devlink->ops->sb_pool_get) 1146 return -EOPNOTSUPP; 1147 1148 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1149 if (!msg) 1150 return -ENOMEM; 1151 1152 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 1153 DEVLINK_CMD_SB_POOL_NEW, 1154 info->snd_portid, info->snd_seq, 0); 1155 if (err) { 1156 nlmsg_free(msg); 1157 return err; 1158 } 1159 1160 return genlmsg_reply(msg, info); 1161} 1162 1163static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1164 struct devlink *devlink, 1165 struct devlink_sb *devlink_sb, 1166 u32 portid, u32 seq) 1167{ 1168 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1169 u16 pool_index; 1170 int err; 1171 1172 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1173 if (*p_idx < start) { 1174 (*p_idx)++; 1175 continue; 1176 } 1177 err = devlink_nl_sb_pool_fill(msg, devlink, 1178 devlink_sb, 1179 pool_index, 1180 DEVLINK_CMD_SB_POOL_NEW, 1181 portid, seq, NLM_F_MULTI); 1182 if (err) 1183 return err; 1184 (*p_idx)++; 1185 } 1186 return 0; 1187} 1188 1189static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, 1190 struct netlink_callback *cb) 1191{ 1192 struct devlink *devlink; 1193 struct devlink_sb *devlink_sb; 1194 int start = cb->args[0]; 1195 int idx = 0; 1196 int err = 0; 1197 1198 mutex_lock(&devlink_mutex); 1199 list_for_each_entry(devlink, &devlink_list, list) { 1200 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1201 !devlink->ops->sb_pool_get) 1202 continue; 1203 mutex_lock(&devlink->lock); 1204 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1205 err = __sb_pool_get_dumpit(msg, start, &idx, devlink, 1206 devlink_sb, 1207 NETLINK_CB(cb->skb).portid, 1208 cb->nlh->nlmsg_seq); 1209 if (err == -EOPNOTSUPP) { 1210 err = 0; 1211 } else if (err) { 1212 mutex_unlock(&devlink->lock); 1213 goto out; 1214 } 1215 } 1216 mutex_unlock(&devlink->lock); 1217 } 1218out: 1219 mutex_unlock(&devlink_mutex); 1220 1221 if (err != -EMSGSIZE) 1222 return err; 1223 1224 cb->args[0] = idx; 1225 return msg->len; 1226} 1227 1228static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 1229 u16 pool_index, u32 size, 1230 enum devlink_sb_threshold_type threshold_type, 1231 struct netlink_ext_ack *extack) 1232 1233{ 1234 const struct devlink_ops *ops = devlink->ops; 1235 1236 if (ops->sb_pool_set) 1237 return ops->sb_pool_set(devlink, sb_index, pool_index, 1238 size, threshold_type, extack); 1239 return -EOPNOTSUPP; 1240} 1241 1242static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 1243 struct genl_info *info) 1244{ 1245 struct devlink *devlink = info->user_ptr[0]; 1246 enum devlink_sb_threshold_type threshold_type; 1247 struct devlink_sb *devlink_sb; 1248 u16 pool_index; 1249 u32 size; 1250 int err; 1251 1252 devlink_sb = devlink_sb_get_from_info(devlink, info); 1253 if (IS_ERR(devlink_sb)) 1254 return PTR_ERR(devlink_sb); 1255 1256 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1257 &pool_index); 1258 if (err) 1259 return err; 1260 1261 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 1262 if (err) 1263 return err; 1264 1265 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) 1266 return -EINVAL; 1267 1268 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 1269 return devlink_sb_pool_set(devlink, devlink_sb->index, 1270 pool_index, size, threshold_type, 1271 info->extack); 1272} 1273 1274static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 1275 struct devlink *devlink, 1276 struct devlink_port *devlink_port, 1277 struct devlink_sb *devlink_sb, 1278 u16 pool_index, 1279 enum devlink_command cmd, 1280 u32 portid, u32 seq, int flags) 1281{ 1282 const struct devlink_ops *ops = devlink->ops; 1283 u32 threshold; 1284 void *hdr; 1285 int err; 1286 1287 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 1288 pool_index, &threshold); 1289 if (err) 1290 return err; 1291 1292 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1293 if (!hdr) 1294 return -EMSGSIZE; 1295 1296 if (devlink_nl_put_handle(msg, devlink)) 1297 goto nla_put_failure; 1298 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1299 goto nla_put_failure; 1300 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1301 goto nla_put_failure; 1302 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1303 goto nla_put_failure; 1304 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1305 goto nla_put_failure; 1306 1307 if (ops->sb_occ_port_pool_get) { 1308 u32 cur; 1309 u32 max; 1310 1311 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 1312 pool_index, &cur, &max); 1313 if (err && err != -EOPNOTSUPP) 1314 return err; 1315 if (!err) { 1316 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1317 goto nla_put_failure; 1318 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1319 goto nla_put_failure; 1320 } 1321 } 1322 1323 genlmsg_end(msg, hdr); 1324 return 0; 1325 1326nla_put_failure: 1327 genlmsg_cancel(msg, hdr); 1328 return -EMSGSIZE; 1329} 1330 1331static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, 1332 struct genl_info *info) 1333{ 1334 struct devlink_port *devlink_port = info->user_ptr[1]; 1335 struct devlink *devlink = devlink_port->devlink; 1336 struct devlink_sb *devlink_sb; 1337 struct sk_buff *msg; 1338 u16 pool_index; 1339 int err; 1340 1341 devlink_sb = devlink_sb_get_from_info(devlink, info); 1342 if (IS_ERR(devlink_sb)) 1343 return PTR_ERR(devlink_sb); 1344 1345 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1346 &pool_index); 1347 if (err) 1348 return err; 1349 1350 if (!devlink->ops->sb_port_pool_get) 1351 return -EOPNOTSUPP; 1352 1353 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1354 if (!msg) 1355 return -ENOMEM; 1356 1357 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 1358 devlink_sb, pool_index, 1359 DEVLINK_CMD_SB_PORT_POOL_NEW, 1360 info->snd_portid, info->snd_seq, 0); 1361 if (err) { 1362 nlmsg_free(msg); 1363 return err; 1364 } 1365 1366 return genlmsg_reply(msg, info); 1367} 1368 1369static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1370 struct devlink *devlink, 1371 struct devlink_sb *devlink_sb, 1372 u32 portid, u32 seq) 1373{ 1374 struct devlink_port *devlink_port; 1375 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1376 u16 pool_index; 1377 int err; 1378 1379 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1380 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1381 if (*p_idx < start) { 1382 (*p_idx)++; 1383 continue; 1384 } 1385 err = devlink_nl_sb_port_pool_fill(msg, devlink, 1386 devlink_port, 1387 devlink_sb, 1388 pool_index, 1389 DEVLINK_CMD_SB_PORT_POOL_NEW, 1390 portid, seq, 1391 NLM_F_MULTI); 1392 if (err) 1393 return err; 1394 (*p_idx)++; 1395 } 1396 } 1397 return 0; 1398} 1399 1400static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, 1401 struct netlink_callback *cb) 1402{ 1403 struct devlink *devlink; 1404 struct devlink_sb *devlink_sb; 1405 int start = cb->args[0]; 1406 int idx = 0; 1407 int err = 0; 1408 1409 mutex_lock(&devlink_mutex); 1410 list_for_each_entry(devlink, &devlink_list, list) { 1411 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1412 !devlink->ops->sb_port_pool_get) 1413 continue; 1414 mutex_lock(&devlink->lock); 1415 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1416 err = __sb_port_pool_get_dumpit(msg, start, &idx, 1417 devlink, devlink_sb, 1418 NETLINK_CB(cb->skb).portid, 1419 cb->nlh->nlmsg_seq); 1420 if (err == -EOPNOTSUPP) { 1421 err = 0; 1422 } else if (err) { 1423 mutex_unlock(&devlink->lock); 1424 goto out; 1425 } 1426 } 1427 mutex_unlock(&devlink->lock); 1428 } 1429out: 1430 mutex_unlock(&devlink_mutex); 1431 1432 if (err != -EMSGSIZE) 1433 return err; 1434 1435 cb->args[0] = idx; 1436 return msg->len; 1437} 1438 1439static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1440 unsigned int sb_index, u16 pool_index, 1441 u32 threshold, 1442 struct netlink_ext_ack *extack) 1443 1444{ 1445 const struct devlink_ops *ops = devlink_port->devlink->ops; 1446 1447 if (ops->sb_port_pool_set) 1448 return ops->sb_port_pool_set(devlink_port, sb_index, 1449 pool_index, threshold, extack); 1450 return -EOPNOTSUPP; 1451} 1452 1453static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 1454 struct genl_info *info) 1455{ 1456 struct devlink_port *devlink_port = info->user_ptr[1]; 1457 struct devlink *devlink = info->user_ptr[0]; 1458 struct devlink_sb *devlink_sb; 1459 u16 pool_index; 1460 u32 threshold; 1461 int err; 1462 1463 devlink_sb = devlink_sb_get_from_info(devlink, info); 1464 if (IS_ERR(devlink_sb)) 1465 return PTR_ERR(devlink_sb); 1466 1467 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1468 &pool_index); 1469 if (err) 1470 return err; 1471 1472 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1473 return -EINVAL; 1474 1475 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1476 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 1477 pool_index, threshold, info->extack); 1478} 1479 1480static int 1481devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 1482 struct devlink_port *devlink_port, 1483 struct devlink_sb *devlink_sb, u16 tc_index, 1484 enum devlink_sb_pool_type pool_type, 1485 enum devlink_command cmd, 1486 u32 portid, u32 seq, int flags) 1487{ 1488 const struct devlink_ops *ops = devlink->ops; 1489 u16 pool_index; 1490 u32 threshold; 1491 void *hdr; 1492 int err; 1493 1494 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1495 tc_index, pool_type, 1496 &pool_index, &threshold); 1497 if (err) 1498 return err; 1499 1500 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1501 if (!hdr) 1502 return -EMSGSIZE; 1503 1504 if (devlink_nl_put_handle(msg, devlink)) 1505 goto nla_put_failure; 1506 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1507 goto nla_put_failure; 1508 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1509 goto nla_put_failure; 1510 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 1511 goto nla_put_failure; 1512 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 1513 goto nla_put_failure; 1514 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1515 goto nla_put_failure; 1516 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1517 goto nla_put_failure; 1518 1519 if (ops->sb_occ_tc_port_bind_get) { 1520 u32 cur; 1521 u32 max; 1522 1523 err = ops->sb_occ_tc_port_bind_get(devlink_port, 1524 devlink_sb->index, 1525 tc_index, pool_type, 1526 &cur, &max); 1527 if (err && err != -EOPNOTSUPP) 1528 return err; 1529 if (!err) { 1530 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1531 goto nla_put_failure; 1532 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1533 goto nla_put_failure; 1534 } 1535 } 1536 1537 genlmsg_end(msg, hdr); 1538 return 0; 1539 1540nla_put_failure: 1541 genlmsg_cancel(msg, hdr); 1542 return -EMSGSIZE; 1543} 1544 1545static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 1546 struct genl_info *info) 1547{ 1548 struct devlink_port *devlink_port = info->user_ptr[1]; 1549 struct devlink *devlink = devlink_port->devlink; 1550 struct devlink_sb *devlink_sb; 1551 struct sk_buff *msg; 1552 enum devlink_sb_pool_type pool_type; 1553 u16 tc_index; 1554 int err; 1555 1556 devlink_sb = devlink_sb_get_from_info(devlink, info); 1557 if (IS_ERR(devlink_sb)) 1558 return PTR_ERR(devlink_sb); 1559 1560 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1561 if (err) 1562 return err; 1563 1564 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1565 pool_type, &tc_index); 1566 if (err) 1567 return err; 1568 1569 if (!devlink->ops->sb_tc_pool_bind_get) 1570 return -EOPNOTSUPP; 1571 1572 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1573 if (!msg) 1574 return -ENOMEM; 1575 1576 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 1577 devlink_sb, tc_index, pool_type, 1578 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1579 info->snd_portid, 1580 info->snd_seq, 0); 1581 if (err) { 1582 nlmsg_free(msg); 1583 return err; 1584 } 1585 1586 return genlmsg_reply(msg, info); 1587} 1588 1589static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1590 int start, int *p_idx, 1591 struct devlink *devlink, 1592 struct devlink_sb *devlink_sb, 1593 u32 portid, u32 seq) 1594{ 1595 struct devlink_port *devlink_port; 1596 u16 tc_index; 1597 int err; 1598 1599 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1600 for (tc_index = 0; 1601 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 1602 if (*p_idx < start) { 1603 (*p_idx)++; 1604 continue; 1605 } 1606 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1607 devlink_port, 1608 devlink_sb, 1609 tc_index, 1610 DEVLINK_SB_POOL_TYPE_INGRESS, 1611 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1612 portid, seq, 1613 NLM_F_MULTI); 1614 if (err) 1615 return err; 1616 (*p_idx)++; 1617 } 1618 for (tc_index = 0; 1619 tc_index < devlink_sb->egress_tc_count; tc_index++) { 1620 if (*p_idx < start) { 1621 (*p_idx)++; 1622 continue; 1623 } 1624 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1625 devlink_port, 1626 devlink_sb, 1627 tc_index, 1628 DEVLINK_SB_POOL_TYPE_EGRESS, 1629 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1630 portid, seq, 1631 NLM_F_MULTI); 1632 if (err) 1633 return err; 1634 (*p_idx)++; 1635 } 1636 } 1637 return 0; 1638} 1639 1640static int 1641devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1642 struct netlink_callback *cb) 1643{ 1644 struct devlink *devlink; 1645 struct devlink_sb *devlink_sb; 1646 int start = cb->args[0]; 1647 int idx = 0; 1648 int err = 0; 1649 1650 mutex_lock(&devlink_mutex); 1651 list_for_each_entry(devlink, &devlink_list, list) { 1652 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1653 !devlink->ops->sb_tc_pool_bind_get) 1654 continue; 1655 1656 mutex_lock(&devlink->lock); 1657 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1658 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, 1659 devlink, 1660 devlink_sb, 1661 NETLINK_CB(cb->skb).portid, 1662 cb->nlh->nlmsg_seq); 1663 if (err == -EOPNOTSUPP) { 1664 err = 0; 1665 } else if (err) { 1666 mutex_unlock(&devlink->lock); 1667 goto out; 1668 } 1669 } 1670 mutex_unlock(&devlink->lock); 1671 } 1672out: 1673 mutex_unlock(&devlink_mutex); 1674 1675 if (err != -EMSGSIZE) 1676 return err; 1677 1678 cb->args[0] = idx; 1679 return msg->len; 1680} 1681 1682static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1683 unsigned int sb_index, u16 tc_index, 1684 enum devlink_sb_pool_type pool_type, 1685 u16 pool_index, u32 threshold, 1686 struct netlink_ext_ack *extack) 1687 1688{ 1689 const struct devlink_ops *ops = devlink_port->devlink->ops; 1690 1691 if (ops->sb_tc_pool_bind_set) 1692 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 1693 tc_index, pool_type, 1694 pool_index, threshold, extack); 1695 return -EOPNOTSUPP; 1696} 1697 1698static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 1699 struct genl_info *info) 1700{ 1701 struct devlink_port *devlink_port = info->user_ptr[1]; 1702 struct devlink *devlink = info->user_ptr[0]; 1703 enum devlink_sb_pool_type pool_type; 1704 struct devlink_sb *devlink_sb; 1705 u16 tc_index; 1706 u16 pool_index; 1707 u32 threshold; 1708 int err; 1709 1710 devlink_sb = devlink_sb_get_from_info(devlink, info); 1711 if (IS_ERR(devlink_sb)) 1712 return PTR_ERR(devlink_sb); 1713 1714 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1715 if (err) 1716 return err; 1717 1718 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1719 pool_type, &tc_index); 1720 if (err) 1721 return err; 1722 1723 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1724 &pool_index); 1725 if (err) 1726 return err; 1727 1728 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1729 return -EINVAL; 1730 1731 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1732 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 1733 tc_index, pool_type, 1734 pool_index, threshold, info->extack); 1735} 1736 1737static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 1738 struct genl_info *info) 1739{ 1740 struct devlink *devlink = info->user_ptr[0]; 1741 const struct devlink_ops *ops = devlink->ops; 1742 struct devlink_sb *devlink_sb; 1743 1744 devlink_sb = devlink_sb_get_from_info(devlink, info); 1745 if (IS_ERR(devlink_sb)) 1746 return PTR_ERR(devlink_sb); 1747 1748 if (ops->sb_occ_snapshot) 1749 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 1750 return -EOPNOTSUPP; 1751} 1752 1753static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 1754 struct genl_info *info) 1755{ 1756 struct devlink *devlink = info->user_ptr[0]; 1757 const struct devlink_ops *ops = devlink->ops; 1758 struct devlink_sb *devlink_sb; 1759 1760 devlink_sb = devlink_sb_get_from_info(devlink, info); 1761 if (IS_ERR(devlink_sb)) 1762 return PTR_ERR(devlink_sb); 1763 1764 if (ops->sb_occ_max_clear) 1765 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 1766 return -EOPNOTSUPP; 1767} 1768 1769static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, 1770 enum devlink_command cmd, u32 portid, 1771 u32 seq, int flags) 1772{ 1773 const struct devlink_ops *ops = devlink->ops; 1774 enum devlink_eswitch_encap_mode encap_mode; 1775 u8 inline_mode; 1776 void *hdr; 1777 int err = 0; 1778 u16 mode; 1779 1780 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1781 if (!hdr) 1782 return -EMSGSIZE; 1783 1784 err = devlink_nl_put_handle(msg, devlink); 1785 if (err) 1786 goto nla_put_failure; 1787 1788 if (ops->eswitch_mode_get) { 1789 err = ops->eswitch_mode_get(devlink, &mode); 1790 if (err) 1791 goto nla_put_failure; 1792 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode); 1793 if (err) 1794 goto nla_put_failure; 1795 } 1796 1797 if (ops->eswitch_inline_mode_get) { 1798 err = ops->eswitch_inline_mode_get(devlink, &inline_mode); 1799 if (err) 1800 goto nla_put_failure; 1801 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, 1802 inline_mode); 1803 if (err) 1804 goto nla_put_failure; 1805 } 1806 1807 if (ops->eswitch_encap_mode_get) { 1808 err = ops->eswitch_encap_mode_get(devlink, &encap_mode); 1809 if (err) 1810 goto nla_put_failure; 1811 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode); 1812 if (err) 1813 goto nla_put_failure; 1814 } 1815 1816 genlmsg_end(msg, hdr); 1817 return 0; 1818 1819nla_put_failure: 1820 genlmsg_cancel(msg, hdr); 1821 return err; 1822} 1823 1824static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, 1825 struct genl_info *info) 1826{ 1827 struct devlink *devlink = info->user_ptr[0]; 1828 struct sk_buff *msg; 1829 int err; 1830 1831 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1832 if (!msg) 1833 return -ENOMEM; 1834 1835 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET, 1836 info->snd_portid, info->snd_seq, 0); 1837 1838 if (err) { 1839 nlmsg_free(msg); 1840 return err; 1841 } 1842 1843 return genlmsg_reply(msg, info); 1844} 1845 1846static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, 1847 struct genl_info *info) 1848{ 1849 struct devlink *devlink = info->user_ptr[0]; 1850 const struct devlink_ops *ops = devlink->ops; 1851 enum devlink_eswitch_encap_mode encap_mode; 1852 u8 inline_mode; 1853 int err = 0; 1854 u16 mode; 1855 1856 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) { 1857 if (!ops->eswitch_mode_set) 1858 return -EOPNOTSUPP; 1859 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); 1860 err = ops->eswitch_mode_set(devlink, mode, info->extack); 1861 if (err) 1862 return err; 1863 } 1864 1865 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { 1866 if (!ops->eswitch_inline_mode_set) 1867 return -EOPNOTSUPP; 1868 inline_mode = nla_get_u8( 1869 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]); 1870 err = ops->eswitch_inline_mode_set(devlink, inline_mode, 1871 info->extack); 1872 if (err) 1873 return err; 1874 } 1875 1876 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) { 1877 if (!ops->eswitch_encap_mode_set) 1878 return -EOPNOTSUPP; 1879 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]); 1880 err = ops->eswitch_encap_mode_set(devlink, encap_mode, 1881 info->extack); 1882 if (err) 1883 return err; 1884 } 1885 1886 return 0; 1887} 1888 1889int devlink_dpipe_match_put(struct sk_buff *skb, 1890 struct devlink_dpipe_match *match) 1891{ 1892 struct devlink_dpipe_header *header = match->header; 1893 struct devlink_dpipe_field *field = &header->fields[match->field_id]; 1894 struct nlattr *match_attr; 1895 1896 match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH); 1897 if (!match_attr) 1898 return -EMSGSIZE; 1899 1900 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 1901 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 1902 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1903 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1904 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1905 goto nla_put_failure; 1906 1907 nla_nest_end(skb, match_attr); 1908 return 0; 1909 1910nla_put_failure: 1911 nla_nest_cancel(skb, match_attr); 1912 return -EMSGSIZE; 1913} 1914EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 1915 1916static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 1917 struct sk_buff *skb) 1918{ 1919 struct nlattr *matches_attr; 1920 1921 matches_attr = nla_nest_start_noflag(skb, 1922 DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 1923 if (!matches_attr) 1924 return -EMSGSIZE; 1925 1926 if (table->table_ops->matches_dump(table->priv, skb)) 1927 goto nla_put_failure; 1928 1929 nla_nest_end(skb, matches_attr); 1930 return 0; 1931 1932nla_put_failure: 1933 nla_nest_cancel(skb, matches_attr); 1934 return -EMSGSIZE; 1935} 1936 1937int devlink_dpipe_action_put(struct sk_buff *skb, 1938 struct devlink_dpipe_action *action) 1939{ 1940 struct devlink_dpipe_header *header = action->header; 1941 struct devlink_dpipe_field *field = &header->fields[action->field_id]; 1942 struct nlattr *action_attr; 1943 1944 action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION); 1945 if (!action_attr) 1946 return -EMSGSIZE; 1947 1948 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 1949 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 1950 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1951 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1952 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1953 goto nla_put_failure; 1954 1955 nla_nest_end(skb, action_attr); 1956 return 0; 1957 1958nla_put_failure: 1959 nla_nest_cancel(skb, action_attr); 1960 return -EMSGSIZE; 1961} 1962EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 1963 1964static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 1965 struct sk_buff *skb) 1966{ 1967 struct nlattr *actions_attr; 1968 1969 actions_attr = nla_nest_start_noflag(skb, 1970 DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 1971 if (!actions_attr) 1972 return -EMSGSIZE; 1973 1974 if (table->table_ops->actions_dump(table->priv, skb)) 1975 goto nla_put_failure; 1976 1977 nla_nest_end(skb, actions_attr); 1978 return 0; 1979 1980nla_put_failure: 1981 nla_nest_cancel(skb, actions_attr); 1982 return -EMSGSIZE; 1983} 1984 1985static int devlink_dpipe_table_put(struct sk_buff *skb, 1986 struct devlink_dpipe_table *table) 1987{ 1988 struct nlattr *table_attr; 1989 u64 table_size; 1990 1991 table_size = table->table_ops->size_get(table->priv); 1992 table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE); 1993 if (!table_attr) 1994 return -EMSGSIZE; 1995 1996 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 1997 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 1998 DEVLINK_ATTR_PAD)) 1999 goto nla_put_failure; 2000 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 2001 table->counters_enabled)) 2002 goto nla_put_failure; 2003 2004 if (table->resource_valid) { 2005 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 2006 table->resource_id, DEVLINK_ATTR_PAD) || 2007 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 2008 table->resource_units, DEVLINK_ATTR_PAD)) 2009 goto nla_put_failure; 2010 } 2011 if (devlink_dpipe_matches_put(table, skb)) 2012 goto nla_put_failure; 2013 2014 if (devlink_dpipe_actions_put(table, skb)) 2015 goto nla_put_failure; 2016 2017 nla_nest_end(skb, table_attr); 2018 return 0; 2019 2020nla_put_failure: 2021 nla_nest_cancel(skb, table_attr); 2022 return -EMSGSIZE; 2023} 2024 2025static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 2026 struct genl_info *info) 2027{ 2028 int err; 2029 2030 if (*pskb) { 2031 err = genlmsg_reply(*pskb, info); 2032 if (err) 2033 return err; 2034 } 2035 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 2036 if (!*pskb) 2037 return -ENOMEM; 2038 return 0; 2039} 2040 2041static int devlink_dpipe_tables_fill(struct genl_info *info, 2042 enum devlink_command cmd, int flags, 2043 struct list_head *dpipe_tables, 2044 const char *table_name) 2045{ 2046 struct devlink *devlink = info->user_ptr[0]; 2047 struct devlink_dpipe_table *table; 2048 struct nlattr *tables_attr; 2049 struct sk_buff *skb = NULL; 2050 struct nlmsghdr *nlh; 2051 bool incomplete; 2052 void *hdr; 2053 int i; 2054 int err; 2055 2056 table = list_first_entry(dpipe_tables, 2057 struct devlink_dpipe_table, list); 2058start_again: 2059 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2060 if (err) 2061 return err; 2062 2063 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2064 &devlink_nl_family, NLM_F_MULTI, cmd); 2065 if (!hdr) { 2066 nlmsg_free(skb); 2067 return -EMSGSIZE; 2068 } 2069 2070 if (devlink_nl_put_handle(skb, devlink)) 2071 goto nla_put_failure; 2072 tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES); 2073 if (!tables_attr) 2074 goto nla_put_failure; 2075 2076 i = 0; 2077 incomplete = false; 2078 list_for_each_entry_from(table, dpipe_tables, list) { 2079 if (!table_name) { 2080 err = devlink_dpipe_table_put(skb, table); 2081 if (err) { 2082 if (!i) 2083 goto err_table_put; 2084 incomplete = true; 2085 break; 2086 } 2087 } else { 2088 if (!strcmp(table->name, table_name)) { 2089 err = devlink_dpipe_table_put(skb, table); 2090 if (err) 2091 break; 2092 } 2093 } 2094 i++; 2095 } 2096 2097 nla_nest_end(skb, tables_attr); 2098 genlmsg_end(skb, hdr); 2099 if (incomplete) 2100 goto start_again; 2101 2102send_done: 2103 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2104 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2105 if (!nlh) { 2106 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2107 if (err) 2108 return err; 2109 goto send_done; 2110 } 2111 2112 return genlmsg_reply(skb, info); 2113 2114nla_put_failure: 2115 err = -EMSGSIZE; 2116err_table_put: 2117 nlmsg_free(skb); 2118 return err; 2119} 2120 2121static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 2122 struct genl_info *info) 2123{ 2124 struct devlink *devlink = info->user_ptr[0]; 2125 const char *table_name = NULL; 2126 2127 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2128 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2129 2130 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 2131 &devlink->dpipe_table_list, 2132 table_name); 2133} 2134 2135static int devlink_dpipe_value_put(struct sk_buff *skb, 2136 struct devlink_dpipe_value *value) 2137{ 2138 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 2139 value->value_size, value->value)) 2140 return -EMSGSIZE; 2141 if (value->mask) 2142 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 2143 value->value_size, value->mask)) 2144 return -EMSGSIZE; 2145 if (value->mapping_valid) 2146 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 2147 value->mapping_value)) 2148 return -EMSGSIZE; 2149 return 0; 2150} 2151 2152static int devlink_dpipe_action_value_put(struct sk_buff *skb, 2153 struct devlink_dpipe_value *value) 2154{ 2155 if (!value->action) 2156 return -EINVAL; 2157 if (devlink_dpipe_action_put(skb, value->action)) 2158 return -EMSGSIZE; 2159 if (devlink_dpipe_value_put(skb, value)) 2160 return -EMSGSIZE; 2161 return 0; 2162} 2163 2164static int devlink_dpipe_action_values_put(struct sk_buff *skb, 2165 struct devlink_dpipe_value *values, 2166 unsigned int values_count) 2167{ 2168 struct nlattr *action_attr; 2169 int i; 2170 int err; 2171 2172 for (i = 0; i < values_count; i++) { 2173 action_attr = nla_nest_start_noflag(skb, 2174 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 2175 if (!action_attr) 2176 return -EMSGSIZE; 2177 err = devlink_dpipe_action_value_put(skb, &values[i]); 2178 if (err) 2179 goto err_action_value_put; 2180 nla_nest_end(skb, action_attr); 2181 } 2182 return 0; 2183 2184err_action_value_put: 2185 nla_nest_cancel(skb, action_attr); 2186 return err; 2187} 2188 2189static int devlink_dpipe_match_value_put(struct sk_buff *skb, 2190 struct devlink_dpipe_value *value) 2191{ 2192 if (!value->match) 2193 return -EINVAL; 2194 if (devlink_dpipe_match_put(skb, value->match)) 2195 return -EMSGSIZE; 2196 if (devlink_dpipe_value_put(skb, value)) 2197 return -EMSGSIZE; 2198 return 0; 2199} 2200 2201static int devlink_dpipe_match_values_put(struct sk_buff *skb, 2202 struct devlink_dpipe_value *values, 2203 unsigned int values_count) 2204{ 2205 struct nlattr *match_attr; 2206 int i; 2207 int err; 2208 2209 for (i = 0; i < values_count; i++) { 2210 match_attr = nla_nest_start_noflag(skb, 2211 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 2212 if (!match_attr) 2213 return -EMSGSIZE; 2214 err = devlink_dpipe_match_value_put(skb, &values[i]); 2215 if (err) 2216 goto err_match_value_put; 2217 nla_nest_end(skb, match_attr); 2218 } 2219 return 0; 2220 2221err_match_value_put: 2222 nla_nest_cancel(skb, match_attr); 2223 return err; 2224} 2225 2226static int devlink_dpipe_entry_put(struct sk_buff *skb, 2227 struct devlink_dpipe_entry *entry) 2228{ 2229 struct nlattr *entry_attr, *matches_attr, *actions_attr; 2230 int err; 2231 2232 entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY); 2233 if (!entry_attr) 2234 return -EMSGSIZE; 2235 2236 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 2237 DEVLINK_ATTR_PAD)) 2238 goto nla_put_failure; 2239 if (entry->counter_valid) 2240 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 2241 entry->counter, DEVLINK_ATTR_PAD)) 2242 goto nla_put_failure; 2243 2244 matches_attr = nla_nest_start_noflag(skb, 2245 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 2246 if (!matches_attr) 2247 goto nla_put_failure; 2248 2249 err = devlink_dpipe_match_values_put(skb, entry->match_values, 2250 entry->match_values_count); 2251 if (err) { 2252 nla_nest_cancel(skb, matches_attr); 2253 goto err_match_values_put; 2254 } 2255 nla_nest_end(skb, matches_attr); 2256 2257 actions_attr = nla_nest_start_noflag(skb, 2258 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 2259 if (!actions_attr) 2260 goto nla_put_failure; 2261 2262 err = devlink_dpipe_action_values_put(skb, entry->action_values, 2263 entry->action_values_count); 2264 if (err) { 2265 nla_nest_cancel(skb, actions_attr); 2266 goto err_action_values_put; 2267 } 2268 nla_nest_end(skb, actions_attr); 2269 2270 nla_nest_end(skb, entry_attr); 2271 return 0; 2272 2273nla_put_failure: 2274 err = -EMSGSIZE; 2275err_match_values_put: 2276err_action_values_put: 2277 nla_nest_cancel(skb, entry_attr); 2278 return err; 2279} 2280 2281static struct devlink_dpipe_table * 2282devlink_dpipe_table_find(struct list_head *dpipe_tables, 2283 const char *table_name, struct devlink *devlink) 2284{ 2285 struct devlink_dpipe_table *table; 2286 list_for_each_entry_rcu(table, dpipe_tables, list, 2287 lockdep_is_held(&devlink->lock)) { 2288 if (!strcmp(table->name, table_name)) 2289 return table; 2290 } 2291 return NULL; 2292} 2293 2294int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 2295{ 2296 struct devlink *devlink; 2297 int err; 2298 2299 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 2300 dump_ctx->info); 2301 if (err) 2302 return err; 2303 2304 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 2305 dump_ctx->info->snd_portid, 2306 dump_ctx->info->snd_seq, 2307 &devlink_nl_family, NLM_F_MULTI, 2308 dump_ctx->cmd); 2309 if (!dump_ctx->hdr) 2310 goto nla_put_failure; 2311 2312 devlink = dump_ctx->info->user_ptr[0]; 2313 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2314 goto nla_put_failure; 2315 dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb, 2316 DEVLINK_ATTR_DPIPE_ENTRIES); 2317 if (!dump_ctx->nest) 2318 goto nla_put_failure; 2319 return 0; 2320 2321nla_put_failure: 2322 nlmsg_free(dump_ctx->skb); 2323 return -EMSGSIZE; 2324} 2325EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2326 2327int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2328 struct devlink_dpipe_entry *entry) 2329{ 2330 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2331} 2332EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2333 2334int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2335{ 2336 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2337 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2338 return 0; 2339} 2340EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2341 2342void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2343 2344{ 2345 unsigned int value_count, value_index; 2346 struct devlink_dpipe_value *value; 2347 2348 value = entry->action_values; 2349 value_count = entry->action_values_count; 2350 for (value_index = 0; value_index < value_count; value_index++) { 2351 kfree(value[value_index].value); 2352 kfree(value[value_index].mask); 2353 } 2354 2355 value = entry->match_values; 2356 value_count = entry->match_values_count; 2357 for (value_index = 0; value_index < value_count; value_index++) { 2358 kfree(value[value_index].value); 2359 kfree(value[value_index].mask); 2360 } 2361} 2362EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2363 2364static int devlink_dpipe_entries_fill(struct genl_info *info, 2365 enum devlink_command cmd, int flags, 2366 struct devlink_dpipe_table *table) 2367{ 2368 struct devlink_dpipe_dump_ctx dump_ctx; 2369 struct nlmsghdr *nlh; 2370 int err; 2371 2372 dump_ctx.skb = NULL; 2373 dump_ctx.cmd = cmd; 2374 dump_ctx.info = info; 2375 2376 err = table->table_ops->entries_dump(table->priv, 2377 table->counters_enabled, 2378 &dump_ctx); 2379 if (err) 2380 return err; 2381 2382send_done: 2383 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2384 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2385 if (!nlh) { 2386 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2387 if (err) 2388 return err; 2389 goto send_done; 2390 } 2391 return genlmsg_reply(dump_ctx.skb, info); 2392} 2393 2394static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2395 struct genl_info *info) 2396{ 2397 struct devlink *devlink = info->user_ptr[0]; 2398 struct devlink_dpipe_table *table; 2399 const char *table_name; 2400 2401 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2402 return -EINVAL; 2403 2404 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2405 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2406 table_name, devlink); 2407 if (!table) 2408 return -EINVAL; 2409 2410 if (!table->table_ops->entries_dump) 2411 return -EINVAL; 2412 2413 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2414 0, table); 2415} 2416 2417static int devlink_dpipe_fields_put(struct sk_buff *skb, 2418 const struct devlink_dpipe_header *header) 2419{ 2420 struct devlink_dpipe_field *field; 2421 struct nlattr *field_attr; 2422 int i; 2423 2424 for (i = 0; i < header->fields_count; i++) { 2425 field = &header->fields[i]; 2426 field_attr = nla_nest_start_noflag(skb, 2427 DEVLINK_ATTR_DPIPE_FIELD); 2428 if (!field_attr) 2429 return -EMSGSIZE; 2430 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2431 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2432 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2433 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2434 goto nla_put_failure; 2435 nla_nest_end(skb, field_attr); 2436 } 2437 return 0; 2438 2439nla_put_failure: 2440 nla_nest_cancel(skb, field_attr); 2441 return -EMSGSIZE; 2442} 2443 2444static int devlink_dpipe_header_put(struct sk_buff *skb, 2445 struct devlink_dpipe_header *header) 2446{ 2447 struct nlattr *fields_attr, *header_attr; 2448 int err; 2449 2450 header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER); 2451 if (!header_attr) 2452 return -EMSGSIZE; 2453 2454 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2455 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2456 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2457 goto nla_put_failure; 2458 2459 fields_attr = nla_nest_start_noflag(skb, 2460 DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2461 if (!fields_attr) 2462 goto nla_put_failure; 2463 2464 err = devlink_dpipe_fields_put(skb, header); 2465 if (err) { 2466 nla_nest_cancel(skb, fields_attr); 2467 goto nla_put_failure; 2468 } 2469 nla_nest_end(skb, fields_attr); 2470 nla_nest_end(skb, header_attr); 2471 return 0; 2472 2473nla_put_failure: 2474 err = -EMSGSIZE; 2475 nla_nest_cancel(skb, header_attr); 2476 return err; 2477} 2478 2479static int devlink_dpipe_headers_fill(struct genl_info *info, 2480 enum devlink_command cmd, int flags, 2481 struct devlink_dpipe_headers * 2482 dpipe_headers) 2483{ 2484 struct devlink *devlink = info->user_ptr[0]; 2485 struct nlattr *headers_attr; 2486 struct sk_buff *skb = NULL; 2487 struct nlmsghdr *nlh; 2488 void *hdr; 2489 int i, j; 2490 int err; 2491 2492 i = 0; 2493start_again: 2494 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2495 if (err) 2496 return err; 2497 2498 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2499 &devlink_nl_family, NLM_F_MULTI, cmd); 2500 if (!hdr) { 2501 nlmsg_free(skb); 2502 return -EMSGSIZE; 2503 } 2504 2505 if (devlink_nl_put_handle(skb, devlink)) 2506 goto nla_put_failure; 2507 headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2508 if (!headers_attr) 2509 goto nla_put_failure; 2510 2511 j = 0; 2512 for (; i < dpipe_headers->headers_count; i++) { 2513 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2514 if (err) { 2515 if (!j) 2516 goto err_table_put; 2517 break; 2518 } 2519 j++; 2520 } 2521 nla_nest_end(skb, headers_attr); 2522 genlmsg_end(skb, hdr); 2523 if (i != dpipe_headers->headers_count) 2524 goto start_again; 2525 2526send_done: 2527 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2528 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2529 if (!nlh) { 2530 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2531 if (err) 2532 return err; 2533 goto send_done; 2534 } 2535 return genlmsg_reply(skb, info); 2536 2537nla_put_failure: 2538 err = -EMSGSIZE; 2539err_table_put: 2540 nlmsg_free(skb); 2541 return err; 2542} 2543 2544static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2545 struct genl_info *info) 2546{ 2547 struct devlink *devlink = info->user_ptr[0]; 2548 2549 if (!devlink->dpipe_headers) 2550 return -EOPNOTSUPP; 2551 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2552 0, devlink->dpipe_headers); 2553} 2554 2555static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2556 const char *table_name, 2557 bool enable) 2558{ 2559 struct devlink_dpipe_table *table; 2560 2561 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2562 table_name, devlink); 2563 if (!table) 2564 return -EINVAL; 2565 2566 if (table->counter_control_extern) 2567 return -EOPNOTSUPP; 2568 2569 if (!(table->counters_enabled ^ enable)) 2570 return 0; 2571 2572 table->counters_enabled = enable; 2573 if (table->table_ops->counters_set_update) 2574 table->table_ops->counters_set_update(table->priv, enable); 2575 return 0; 2576} 2577 2578static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2579 struct genl_info *info) 2580{ 2581 struct devlink *devlink = info->user_ptr[0]; 2582 const char *table_name; 2583 bool counters_enable; 2584 2585 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2586 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2587 return -EINVAL; 2588 2589 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2590 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2591 2592 return devlink_dpipe_table_counters_set(devlink, table_name, 2593 counters_enable); 2594} 2595 2596static struct devlink_resource * 2597devlink_resource_find(struct devlink *devlink, 2598 struct devlink_resource *resource, u64 resource_id) 2599{ 2600 struct list_head *resource_list; 2601 2602 if (resource) 2603 resource_list = &resource->resource_list; 2604 else 2605 resource_list = &devlink->resource_list; 2606 2607 list_for_each_entry(resource, resource_list, list) { 2608 struct devlink_resource *child_resource; 2609 2610 if (resource->id == resource_id) 2611 return resource; 2612 2613 child_resource = devlink_resource_find(devlink, resource, 2614 resource_id); 2615 if (child_resource) 2616 return child_resource; 2617 } 2618 return NULL; 2619} 2620 2621static void 2622devlink_resource_validate_children(struct devlink_resource *resource) 2623{ 2624 struct devlink_resource *child_resource; 2625 bool size_valid = true; 2626 u64 parts_size = 0; 2627 2628 if (list_empty(&resource->resource_list)) 2629 goto out; 2630 2631 list_for_each_entry(child_resource, &resource->resource_list, list) 2632 parts_size += child_resource->size_new; 2633 2634 if (parts_size > resource->size_new) 2635 size_valid = false; 2636out: 2637 resource->size_valid = size_valid; 2638} 2639 2640static int 2641devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 2642 struct netlink_ext_ack *extack) 2643{ 2644 u64 reminder; 2645 int err = 0; 2646 2647 if (size > resource->size_params.size_max) { 2648 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum"); 2649 err = -EINVAL; 2650 } 2651 2652 if (size < resource->size_params.size_min) { 2653 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum"); 2654 err = -EINVAL; 2655 } 2656 2657 div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 2658 if (reminder) { 2659 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity"); 2660 err = -EINVAL; 2661 } 2662 2663 return err; 2664} 2665 2666static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2667 struct genl_info *info) 2668{ 2669 struct devlink *devlink = info->user_ptr[0]; 2670 struct devlink_resource *resource; 2671 u64 resource_id; 2672 u64 size; 2673 int err; 2674 2675 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2676 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2677 return -EINVAL; 2678 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2679 2680 resource = devlink_resource_find(devlink, NULL, resource_id); 2681 if (!resource) 2682 return -EINVAL; 2683 2684 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2685 err = devlink_resource_validate_size(resource, size, info->extack); 2686 if (err) 2687 return err; 2688 2689 resource->size_new = size; 2690 devlink_resource_validate_children(resource); 2691 if (resource->parent) 2692 devlink_resource_validate_children(resource->parent); 2693 return 0; 2694} 2695 2696static int 2697devlink_resource_size_params_put(struct devlink_resource *resource, 2698 struct sk_buff *skb) 2699{ 2700 struct devlink_resource_size_params *size_params; 2701 2702 size_params = &resource->size_params; 2703 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2704 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2705 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2706 size_params->size_max, DEVLINK_ATTR_PAD) || 2707 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2708 size_params->size_min, DEVLINK_ATTR_PAD) || 2709 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2710 return -EMSGSIZE; 2711 return 0; 2712} 2713 2714static int devlink_resource_occ_put(struct devlink_resource *resource, 2715 struct sk_buff *skb) 2716{ 2717 if (!resource->occ_get) 2718 return 0; 2719 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2720 resource->occ_get(resource->occ_get_priv), 2721 DEVLINK_ATTR_PAD); 2722} 2723 2724static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2725 struct devlink_resource *resource) 2726{ 2727 struct devlink_resource *child_resource; 2728 struct nlattr *child_resource_attr; 2729 struct nlattr *resource_attr; 2730 2731 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE); 2732 if (!resource_attr) 2733 return -EMSGSIZE; 2734 2735 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2736 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2737 DEVLINK_ATTR_PAD) || 2738 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2739 DEVLINK_ATTR_PAD)) 2740 goto nla_put_failure; 2741 if (resource->size != resource->size_new) 2742 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2743 resource->size_new, DEVLINK_ATTR_PAD); 2744 if (devlink_resource_occ_put(resource, skb)) 2745 goto nla_put_failure; 2746 if (devlink_resource_size_params_put(resource, skb)) 2747 goto nla_put_failure; 2748 if (list_empty(&resource->resource_list)) 2749 goto out; 2750 2751 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2752 resource->size_valid)) 2753 goto nla_put_failure; 2754 2755 child_resource_attr = nla_nest_start_noflag(skb, 2756 DEVLINK_ATTR_RESOURCE_LIST); 2757 if (!child_resource_attr) 2758 goto nla_put_failure; 2759 2760 list_for_each_entry(child_resource, &resource->resource_list, list) { 2761 if (devlink_resource_put(devlink, skb, child_resource)) 2762 goto resource_put_failure; 2763 } 2764 2765 nla_nest_end(skb, child_resource_attr); 2766out: 2767 nla_nest_end(skb, resource_attr); 2768 return 0; 2769 2770resource_put_failure: 2771 nla_nest_cancel(skb, child_resource_attr); 2772nla_put_failure: 2773 nla_nest_cancel(skb, resource_attr); 2774 return -EMSGSIZE; 2775} 2776 2777static int devlink_resource_fill(struct genl_info *info, 2778 enum devlink_command cmd, int flags) 2779{ 2780 struct devlink *devlink = info->user_ptr[0]; 2781 struct devlink_resource *resource; 2782 struct nlattr *resources_attr; 2783 struct sk_buff *skb = NULL; 2784 struct nlmsghdr *nlh; 2785 bool incomplete; 2786 void *hdr; 2787 int i; 2788 int err; 2789 2790 resource = list_first_entry(&devlink->resource_list, 2791 struct devlink_resource, list); 2792start_again: 2793 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2794 if (err) 2795 return err; 2796 2797 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2798 &devlink_nl_family, NLM_F_MULTI, cmd); 2799 if (!hdr) { 2800 nlmsg_free(skb); 2801 return -EMSGSIZE; 2802 } 2803 2804 if (devlink_nl_put_handle(skb, devlink)) 2805 goto nla_put_failure; 2806 2807 resources_attr = nla_nest_start_noflag(skb, 2808 DEVLINK_ATTR_RESOURCE_LIST); 2809 if (!resources_attr) 2810 goto nla_put_failure; 2811 2812 incomplete = false; 2813 i = 0; 2814 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2815 err = devlink_resource_put(devlink, skb, resource); 2816 if (err) { 2817 if (!i) 2818 goto err_resource_put; 2819 incomplete = true; 2820 break; 2821 } 2822 i++; 2823 } 2824 nla_nest_end(skb, resources_attr); 2825 genlmsg_end(skb, hdr); 2826 if (incomplete) 2827 goto start_again; 2828send_done: 2829 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2830 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2831 if (!nlh) { 2832 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2833 if (err) 2834 return err; 2835 goto send_done; 2836 } 2837 return genlmsg_reply(skb, info); 2838 2839nla_put_failure: 2840 err = -EMSGSIZE; 2841err_resource_put: 2842 nlmsg_free(skb); 2843 return err; 2844} 2845 2846static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2847 struct genl_info *info) 2848{ 2849 struct devlink *devlink = info->user_ptr[0]; 2850 2851 if (list_empty(&devlink->resource_list)) 2852 return -EOPNOTSUPP; 2853 2854 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2855} 2856 2857static int 2858devlink_resources_validate(struct devlink *devlink, 2859 struct devlink_resource *resource, 2860 struct genl_info *info) 2861{ 2862 struct list_head *resource_list; 2863 int err = 0; 2864 2865 if (resource) 2866 resource_list = &resource->resource_list; 2867 else 2868 resource_list = &devlink->resource_list; 2869 2870 list_for_each_entry(resource, resource_list, list) { 2871 if (!resource->size_valid) 2872 return -EINVAL; 2873 err = devlink_resources_validate(devlink, resource, info); 2874 if (err) 2875 return err; 2876 } 2877 return err; 2878} 2879 2880static struct net *devlink_netns_get(struct sk_buff *skb, 2881 struct genl_info *info) 2882{ 2883 struct nlattr *netns_pid_attr = info->attrs[DEVLINK_ATTR_NETNS_PID]; 2884 struct nlattr *netns_fd_attr = info->attrs[DEVLINK_ATTR_NETNS_FD]; 2885 struct nlattr *netns_id_attr = info->attrs[DEVLINK_ATTR_NETNS_ID]; 2886 struct net *net; 2887 2888 if (!!netns_pid_attr + !!netns_fd_attr + !!netns_id_attr > 1) { 2889 NL_SET_ERR_MSG_MOD(info->extack, "multiple netns identifying attributes specified"); 2890 return ERR_PTR(-EINVAL); 2891 } 2892 2893 if (netns_pid_attr) { 2894 net = get_net_ns_by_pid(nla_get_u32(netns_pid_attr)); 2895 } else if (netns_fd_attr) { 2896 net = get_net_ns_by_fd(nla_get_u32(netns_fd_attr)); 2897 } else if (netns_id_attr) { 2898 net = get_net_ns_by_id(sock_net(skb->sk), 2899 nla_get_u32(netns_id_attr)); 2900 if (!net) 2901 net = ERR_PTR(-EINVAL); 2902 } else { 2903 WARN_ON(1); 2904 net = ERR_PTR(-EINVAL); 2905 } 2906 if (IS_ERR(net)) { 2907 NL_SET_ERR_MSG_MOD(info->extack, "Unknown network namespace"); 2908 return ERR_PTR(-EINVAL); 2909 } 2910 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { 2911 put_net(net); 2912 return ERR_PTR(-EPERM); 2913 } 2914 return net; 2915} 2916 2917static void devlink_param_notify(struct devlink *devlink, 2918 unsigned int port_index, 2919 struct devlink_param_item *param_item, 2920 enum devlink_command cmd); 2921 2922static void devlink_reload_netns_change(struct devlink *devlink, 2923 struct net *dest_net) 2924{ 2925 struct devlink_param_item *param_item; 2926 2927 /* Userspace needs to be notified about devlink objects 2928 * removed from original and entering new network namespace. 2929 * The rest of the devlink objects are re-created during 2930 * reload process so the notifications are generated separatelly. 2931 */ 2932 2933 list_for_each_entry(param_item, &devlink->param_list, list) 2934 devlink_param_notify(devlink, 0, param_item, 2935 DEVLINK_CMD_PARAM_DEL); 2936 devlink_notify(devlink, DEVLINK_CMD_DEL); 2937 2938 __devlink_net_set(devlink, dest_net); 2939 2940 devlink_notify(devlink, DEVLINK_CMD_NEW); 2941 list_for_each_entry(param_item, &devlink->param_list, list) 2942 devlink_param_notify(devlink, 0, param_item, 2943 DEVLINK_CMD_PARAM_NEW); 2944} 2945 2946static bool devlink_reload_supported(const struct devlink *devlink) 2947{ 2948 return devlink->ops->reload_down && devlink->ops->reload_up; 2949} 2950 2951static void devlink_reload_failed_set(struct devlink *devlink, 2952 bool reload_failed) 2953{ 2954 if (devlink->reload_failed == reload_failed) 2955 return; 2956 devlink->reload_failed = reload_failed; 2957 devlink_notify(devlink, DEVLINK_CMD_NEW); 2958} 2959 2960bool devlink_is_reload_failed(const struct devlink *devlink) 2961{ 2962 return devlink->reload_failed; 2963} 2964EXPORT_SYMBOL_GPL(devlink_is_reload_failed); 2965 2966static int devlink_reload(struct devlink *devlink, struct net *dest_net, 2967 struct netlink_ext_ack *extack) 2968{ 2969 int err; 2970 2971 if (!devlink->reload_enabled) 2972 return -EOPNOTSUPP; 2973 2974 err = devlink->ops->reload_down(devlink, !!dest_net, extack); 2975 if (err) 2976 return err; 2977 2978 if (dest_net && !net_eq(dest_net, devlink_net(devlink))) 2979 devlink_reload_netns_change(devlink, dest_net); 2980 2981 err = devlink->ops->reload_up(devlink, extack); 2982 devlink_reload_failed_set(devlink, !!err); 2983 return err; 2984} 2985 2986static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2987{ 2988 struct devlink *devlink = info->user_ptr[0]; 2989 struct net *dest_net = NULL; 2990 int err; 2991 2992 if (!devlink_reload_supported(devlink)) 2993 return -EOPNOTSUPP; 2994 2995 err = devlink_resources_validate(devlink, NULL, info); 2996 if (err) { 2997 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2998 return err; 2999 } 3000 3001 if (info->attrs[DEVLINK_ATTR_NETNS_PID] || 3002 info->attrs[DEVLINK_ATTR_NETNS_FD] || 3003 info->attrs[DEVLINK_ATTR_NETNS_ID]) { 3004 dest_net = devlink_netns_get(skb, info); 3005 if (IS_ERR(dest_net)) 3006 return PTR_ERR(dest_net); 3007 } 3008 3009 err = devlink_reload(devlink, dest_net, info->extack); 3010 3011 if (dest_net) 3012 put_net(dest_net); 3013 3014 return err; 3015} 3016 3017static int devlink_nl_flash_update_fill(struct sk_buff *msg, 3018 struct devlink *devlink, 3019 enum devlink_command cmd, 3020 const char *status_msg, 3021 const char *component, 3022 unsigned long done, unsigned long total) 3023{ 3024 void *hdr; 3025 3026 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3027 if (!hdr) 3028 return -EMSGSIZE; 3029 3030 if (devlink_nl_put_handle(msg, devlink)) 3031 goto nla_put_failure; 3032 3033 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS) 3034 goto out; 3035 3036 if (status_msg && 3037 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG, 3038 status_msg)) 3039 goto nla_put_failure; 3040 if (component && 3041 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT, 3042 component)) 3043 goto nla_put_failure; 3044 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE, 3045 done, DEVLINK_ATTR_PAD)) 3046 goto nla_put_failure; 3047 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL, 3048 total, DEVLINK_ATTR_PAD)) 3049 goto nla_put_failure; 3050 3051out: 3052 genlmsg_end(msg, hdr); 3053 return 0; 3054 3055nla_put_failure: 3056 genlmsg_cancel(msg, hdr); 3057 return -EMSGSIZE; 3058} 3059 3060static void __devlink_flash_update_notify(struct devlink *devlink, 3061 enum devlink_command cmd, 3062 const char *status_msg, 3063 const char *component, 3064 unsigned long done, 3065 unsigned long total) 3066{ 3067 struct sk_buff *msg; 3068 int err; 3069 3070 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE && 3071 cmd != DEVLINK_CMD_FLASH_UPDATE_END && 3072 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS); 3073 3074 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3075 if (!msg) 3076 return; 3077 3078 err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg, 3079 component, done, total); 3080 if (err) 3081 goto out_free_msg; 3082 3083 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3084 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3085 return; 3086 3087out_free_msg: 3088 nlmsg_free(msg); 3089} 3090 3091void devlink_flash_update_begin_notify(struct devlink *devlink) 3092{ 3093 __devlink_flash_update_notify(devlink, 3094 DEVLINK_CMD_FLASH_UPDATE, 3095 NULL, NULL, 0, 0); 3096} 3097EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify); 3098 3099void devlink_flash_update_end_notify(struct devlink *devlink) 3100{ 3101 __devlink_flash_update_notify(devlink, 3102 DEVLINK_CMD_FLASH_UPDATE_END, 3103 NULL, NULL, 0, 0); 3104} 3105EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify); 3106 3107void devlink_flash_update_status_notify(struct devlink *devlink, 3108 const char *status_msg, 3109 const char *component, 3110 unsigned long done, 3111 unsigned long total) 3112{ 3113 __devlink_flash_update_notify(devlink, 3114 DEVLINK_CMD_FLASH_UPDATE_STATUS, 3115 status_msg, component, done, total); 3116} 3117EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify); 3118 3119static int devlink_nl_cmd_flash_update(struct sk_buff *skb, 3120 struct genl_info *info) 3121{ 3122 struct devlink *devlink = info->user_ptr[0]; 3123 const char *file_name, *component; 3124 struct nlattr *nla_component; 3125 3126 if (!devlink->ops->flash_update) 3127 return -EOPNOTSUPP; 3128 3129 if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]) 3130 return -EINVAL; 3131 file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]); 3132 3133 nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT]; 3134 component = nla_component ? nla_data(nla_component) : NULL; 3135 3136 return devlink->ops->flash_update(devlink, file_name, component, 3137 info->extack); 3138} 3139 3140static const struct devlink_param devlink_param_generic[] = { 3141 { 3142 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 3143 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 3144 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 3145 }, 3146 { 3147 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 3148 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 3149 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 3150 }, 3151 { 3152 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 3153 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 3154 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 3155 }, 3156 { 3157 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 3158 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 3159 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 3160 }, 3161 { 3162 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, 3163 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME, 3164 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE, 3165 }, 3166 { 3167 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 3168 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME, 3169 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE, 3170 }, 3171 { 3172 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 3173 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME, 3174 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE, 3175 }, 3176 { 3177 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 3178 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, 3179 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, 3180 }, 3181 { 3182 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE, 3183 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME, 3184 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE, 3185 }, 3186 { 3187 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 3188 .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME, 3189 .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE, 3190 }, 3191}; 3192 3193static int devlink_param_generic_verify(const struct devlink_param *param) 3194{ 3195 /* verify it match generic parameter by id and name */ 3196 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 3197 return -EINVAL; 3198 if (strcmp(param->name, devlink_param_generic[param->id].name)) 3199 return -ENOENT; 3200 3201 WARN_ON(param->type != devlink_param_generic[param->id].type); 3202 3203 return 0; 3204} 3205 3206static int devlink_param_driver_verify(const struct devlink_param *param) 3207{ 3208 int i; 3209 3210 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 3211 return -EINVAL; 3212 /* verify no such name in generic params */ 3213 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 3214 if (!strcmp(param->name, devlink_param_generic[i].name)) 3215 return -EEXIST; 3216 3217 return 0; 3218} 3219 3220static struct devlink_param_item * 3221devlink_param_find_by_name(struct list_head *param_list, 3222 const char *param_name) 3223{ 3224 struct devlink_param_item *param_item; 3225 3226 list_for_each_entry(param_item, param_list, list) 3227 if (!strcmp(param_item->param->name, param_name)) 3228 return param_item; 3229 return NULL; 3230} 3231 3232static struct devlink_param_item * 3233devlink_param_find_by_id(struct list_head *param_list, u32 param_id) 3234{ 3235 struct devlink_param_item *param_item; 3236 3237 list_for_each_entry(param_item, param_list, list) 3238 if (param_item->param->id == param_id) 3239 return param_item; 3240 return NULL; 3241} 3242 3243static bool 3244devlink_param_cmode_is_supported(const struct devlink_param *param, 3245 enum devlink_param_cmode cmode) 3246{ 3247 return test_bit(cmode, &param->supported_cmodes); 3248} 3249 3250static int devlink_param_get(struct devlink *devlink, 3251 const struct devlink_param *param, 3252 struct devlink_param_gset_ctx *ctx) 3253{ 3254 if (!param->get) 3255 return -EOPNOTSUPP; 3256 return param->get(devlink, param->id, ctx); 3257} 3258 3259static int devlink_param_set(struct devlink *devlink, 3260 const struct devlink_param *param, 3261 struct devlink_param_gset_ctx *ctx) 3262{ 3263 if (!param->set) 3264 return -EOPNOTSUPP; 3265 return param->set(devlink, param->id, ctx); 3266} 3267 3268static int 3269devlink_param_type_to_nla_type(enum devlink_param_type param_type) 3270{ 3271 switch (param_type) { 3272 case DEVLINK_PARAM_TYPE_U8: 3273 return NLA_U8; 3274 case DEVLINK_PARAM_TYPE_U16: 3275 return NLA_U16; 3276 case DEVLINK_PARAM_TYPE_U32: 3277 return NLA_U32; 3278 case DEVLINK_PARAM_TYPE_STRING: 3279 return NLA_STRING; 3280 case DEVLINK_PARAM_TYPE_BOOL: 3281 return NLA_FLAG; 3282 default: 3283 return -EINVAL; 3284 } 3285} 3286 3287static int 3288devlink_nl_param_value_fill_one(struct sk_buff *msg, 3289 enum devlink_param_type type, 3290 enum devlink_param_cmode cmode, 3291 union devlink_param_value val) 3292{ 3293 struct nlattr *param_value_attr; 3294 3295 param_value_attr = nla_nest_start_noflag(msg, 3296 DEVLINK_ATTR_PARAM_VALUE); 3297 if (!param_value_attr) 3298 goto nla_put_failure; 3299 3300 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 3301 goto value_nest_cancel; 3302 3303 switch (type) { 3304 case DEVLINK_PARAM_TYPE_U8: 3305 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 3306 goto value_nest_cancel; 3307 break; 3308 case DEVLINK_PARAM_TYPE_U16: 3309 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 3310 goto value_nest_cancel; 3311 break; 3312 case DEVLINK_PARAM_TYPE_U32: 3313 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 3314 goto value_nest_cancel; 3315 break; 3316 case DEVLINK_PARAM_TYPE_STRING: 3317 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 3318 val.vstr)) 3319 goto value_nest_cancel; 3320 break; 3321 case DEVLINK_PARAM_TYPE_BOOL: 3322 if (val.vbool && 3323 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 3324 goto value_nest_cancel; 3325 break; 3326 } 3327 3328 nla_nest_end(msg, param_value_attr); 3329 return 0; 3330 3331value_nest_cancel: 3332 nla_nest_cancel(msg, param_value_attr); 3333nla_put_failure: 3334 return -EMSGSIZE; 3335} 3336 3337static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 3338 unsigned int port_index, 3339 struct devlink_param_item *param_item, 3340 enum devlink_command cmd, 3341 u32 portid, u32 seq, int flags) 3342{ 3343 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 3344 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; 3345 const struct devlink_param *param = param_item->param; 3346 struct devlink_param_gset_ctx ctx; 3347 struct nlattr *param_values_list; 3348 struct nlattr *param_attr; 3349 int nla_type; 3350 void *hdr; 3351 int err; 3352 int i; 3353 3354 /* Get value from driver part to driverinit configuration mode */ 3355 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 3356 if (!devlink_param_cmode_is_supported(param, i)) 3357 continue; 3358 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3359 if (!param_item->driverinit_value_valid) 3360 return -EOPNOTSUPP; 3361 param_value[i] = param_item->driverinit_value; 3362 } else { 3363 if (!param_item->published) 3364 continue; 3365 ctx.cmode = i; 3366 err = devlink_param_get(devlink, param, &ctx); 3367 if (err) 3368 return err; 3369 param_value[i] = ctx.val; 3370 } 3371 param_value_set[i] = true; 3372 } 3373 3374 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3375 if (!hdr) 3376 return -EMSGSIZE; 3377 3378 if (devlink_nl_put_handle(msg, devlink)) 3379 goto genlmsg_cancel; 3380 3381 if (cmd == DEVLINK_CMD_PORT_PARAM_GET || 3382 cmd == DEVLINK_CMD_PORT_PARAM_NEW || 3383 cmd == DEVLINK_CMD_PORT_PARAM_DEL) 3384 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index)) 3385 goto genlmsg_cancel; 3386 3387 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM); 3388 if (!param_attr) 3389 goto genlmsg_cancel; 3390 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 3391 goto param_nest_cancel; 3392 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 3393 goto param_nest_cancel; 3394 3395 nla_type = devlink_param_type_to_nla_type(param->type); 3396 if (nla_type < 0) 3397 goto param_nest_cancel; 3398 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 3399 goto param_nest_cancel; 3400 3401 param_values_list = nla_nest_start_noflag(msg, 3402 DEVLINK_ATTR_PARAM_VALUES_LIST); 3403 if (!param_values_list) 3404 goto param_nest_cancel; 3405 3406 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 3407 if (!param_value_set[i]) 3408 continue; 3409 err = devlink_nl_param_value_fill_one(msg, param->type, 3410 i, param_value[i]); 3411 if (err) 3412 goto values_list_nest_cancel; 3413 } 3414 3415 nla_nest_end(msg, param_values_list); 3416 nla_nest_end(msg, param_attr); 3417 genlmsg_end(msg, hdr); 3418 return 0; 3419 3420values_list_nest_cancel: 3421 nla_nest_end(msg, param_values_list); 3422param_nest_cancel: 3423 nla_nest_cancel(msg, param_attr); 3424genlmsg_cancel: 3425 genlmsg_cancel(msg, hdr); 3426 return -EMSGSIZE; 3427} 3428 3429static void devlink_param_notify(struct devlink *devlink, 3430 unsigned int port_index, 3431 struct devlink_param_item *param_item, 3432 enum devlink_command cmd) 3433{ 3434 struct sk_buff *msg; 3435 int err; 3436 3437 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && 3438 cmd != DEVLINK_CMD_PORT_PARAM_NEW && 3439 cmd != DEVLINK_CMD_PORT_PARAM_DEL); 3440 3441 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3442 if (!msg) 3443 return; 3444 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd, 3445 0, 0, 0); 3446 if (err) { 3447 nlmsg_free(msg); 3448 return; 3449 } 3450 3451 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3452 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3453} 3454 3455static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg, 3456 struct netlink_callback *cb) 3457{ 3458 struct devlink_param_item *param_item; 3459 struct devlink *devlink; 3460 int start = cb->args[0]; 3461 int idx = 0; 3462 int err = 0; 3463 3464 mutex_lock(&devlink_mutex); 3465 list_for_each_entry(devlink, &devlink_list, list) { 3466 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3467 continue; 3468 mutex_lock(&devlink->lock); 3469 list_for_each_entry(param_item, &devlink->param_list, list) { 3470 if (idx < start) { 3471 idx++; 3472 continue; 3473 } 3474 err = devlink_nl_param_fill(msg, devlink, 0, param_item, 3475 DEVLINK_CMD_PARAM_GET, 3476 NETLINK_CB(cb->skb).portid, 3477 cb->nlh->nlmsg_seq, 3478 NLM_F_MULTI); 3479 if (err == -EOPNOTSUPP) { 3480 err = 0; 3481 } else if (err) { 3482 mutex_unlock(&devlink->lock); 3483 goto out; 3484 } 3485 idx++; 3486 } 3487 mutex_unlock(&devlink->lock); 3488 } 3489out: 3490 mutex_unlock(&devlink_mutex); 3491 3492 if (err != -EMSGSIZE) 3493 return err; 3494 3495 cb->args[0] = idx; 3496 return msg->len; 3497} 3498 3499static int 3500devlink_param_type_get_from_info(struct genl_info *info, 3501 enum devlink_param_type *param_type) 3502{ 3503 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE]) 3504 return -EINVAL; 3505 3506 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 3507 case NLA_U8: 3508 *param_type = DEVLINK_PARAM_TYPE_U8; 3509 break; 3510 case NLA_U16: 3511 *param_type = DEVLINK_PARAM_TYPE_U16; 3512 break; 3513 case NLA_U32: 3514 *param_type = DEVLINK_PARAM_TYPE_U32; 3515 break; 3516 case NLA_STRING: 3517 *param_type = DEVLINK_PARAM_TYPE_STRING; 3518 break; 3519 case NLA_FLAG: 3520 *param_type = DEVLINK_PARAM_TYPE_BOOL; 3521 break; 3522 default: 3523 return -EINVAL; 3524 } 3525 3526 return 0; 3527} 3528 3529static int 3530devlink_param_value_get_from_info(const struct devlink_param *param, 3531 struct genl_info *info, 3532 union devlink_param_value *value) 3533{ 3534 struct nlattr *param_data; 3535 int len; 3536 3537 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]; 3538 3539 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data) 3540 return -EINVAL; 3541 3542 switch (param->type) { 3543 case DEVLINK_PARAM_TYPE_U8: 3544 if (nla_len(param_data) != sizeof(u8)) 3545 return -EINVAL; 3546 value->vu8 = nla_get_u8(param_data); 3547 break; 3548 case DEVLINK_PARAM_TYPE_U16: 3549 if (nla_len(param_data) != sizeof(u16)) 3550 return -EINVAL; 3551 value->vu16 = nla_get_u16(param_data); 3552 break; 3553 case DEVLINK_PARAM_TYPE_U32: 3554 if (nla_len(param_data) != sizeof(u32)) 3555 return -EINVAL; 3556 value->vu32 = nla_get_u32(param_data); 3557 break; 3558 case DEVLINK_PARAM_TYPE_STRING: 3559 len = strnlen(nla_data(param_data), nla_len(param_data)); 3560 if (len == nla_len(param_data) || 3561 len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 3562 return -EINVAL; 3563 strcpy(value->vstr, nla_data(param_data)); 3564 break; 3565 case DEVLINK_PARAM_TYPE_BOOL: 3566 if (param_data && nla_len(param_data)) 3567 return -EINVAL; 3568 value->vbool = nla_get_flag(param_data); 3569 break; 3570 } 3571 return 0; 3572} 3573 3574static struct devlink_param_item * 3575devlink_param_get_from_info(struct list_head *param_list, 3576 struct genl_info *info) 3577{ 3578 char *param_name; 3579 3580 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME]) 3581 return NULL; 3582 3583 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 3584 return devlink_param_find_by_name(param_list, param_name); 3585} 3586 3587static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb, 3588 struct genl_info *info) 3589{ 3590 struct devlink *devlink = info->user_ptr[0]; 3591 struct devlink_param_item *param_item; 3592 struct sk_buff *msg; 3593 int err; 3594 3595 param_item = devlink_param_get_from_info(&devlink->param_list, info); 3596 if (!param_item) 3597 return -EINVAL; 3598 3599 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3600 if (!msg) 3601 return -ENOMEM; 3602 3603 err = devlink_nl_param_fill(msg, devlink, 0, param_item, 3604 DEVLINK_CMD_PARAM_GET, 3605 info->snd_portid, info->snd_seq, 0); 3606 if (err) { 3607 nlmsg_free(msg); 3608 return err; 3609 } 3610 3611 return genlmsg_reply(msg, info); 3612} 3613 3614static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, 3615 unsigned int port_index, 3616 struct list_head *param_list, 3617 struct genl_info *info, 3618 enum devlink_command cmd) 3619{ 3620 enum devlink_param_type param_type; 3621 struct devlink_param_gset_ctx ctx; 3622 enum devlink_param_cmode cmode; 3623 struct devlink_param_item *param_item; 3624 const struct devlink_param *param; 3625 union devlink_param_value value; 3626 int err = 0; 3627 3628 param_item = devlink_param_get_from_info(param_list, info); 3629 if (!param_item) 3630 return -EINVAL; 3631 param = param_item->param; 3632 err = devlink_param_type_get_from_info(info, &param_type); 3633 if (err) 3634 return err; 3635 if (param_type != param->type) 3636 return -EINVAL; 3637 err = devlink_param_value_get_from_info(param, info, &value); 3638 if (err) 3639 return err; 3640 if (param->validate) { 3641 err = param->validate(devlink, param->id, value, info->extack); 3642 if (err) 3643 return err; 3644 } 3645 3646 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]) 3647 return -EINVAL; 3648 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 3649 if (!devlink_param_cmode_is_supported(param, cmode)) 3650 return -EOPNOTSUPP; 3651 3652 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3653 if (param->type == DEVLINK_PARAM_TYPE_STRING) 3654 strcpy(param_item->driverinit_value.vstr, value.vstr); 3655 else 3656 param_item->driverinit_value = value; 3657 param_item->driverinit_value_valid = true; 3658 } else { 3659 if (!param->set) 3660 return -EOPNOTSUPP; 3661 ctx.val = value; 3662 ctx.cmode = cmode; 3663 err = devlink_param_set(devlink, param, &ctx); 3664 if (err) 3665 return err; 3666 } 3667 3668 devlink_param_notify(devlink, port_index, param_item, cmd); 3669 return 0; 3670} 3671 3672static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 3673 struct genl_info *info) 3674{ 3675 struct devlink *devlink = info->user_ptr[0]; 3676 3677 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list, 3678 info, DEVLINK_CMD_PARAM_NEW); 3679} 3680 3681static int devlink_param_register_one(struct devlink *devlink, 3682 unsigned int port_index, 3683 struct list_head *param_list, 3684 const struct devlink_param *param, 3685 enum devlink_command cmd) 3686{ 3687 struct devlink_param_item *param_item; 3688 3689 if (devlink_param_find_by_name(param_list, param->name)) 3690 return -EEXIST; 3691 3692 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 3693 WARN_ON(param->get || param->set); 3694 else 3695 WARN_ON(!param->get || !param->set); 3696 3697 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 3698 if (!param_item) 3699 return -ENOMEM; 3700 param_item->param = param; 3701 3702 list_add_tail(&param_item->list, param_list); 3703 devlink_param_notify(devlink, port_index, param_item, cmd); 3704 return 0; 3705} 3706 3707static void devlink_param_unregister_one(struct devlink *devlink, 3708 unsigned int port_index, 3709 struct list_head *param_list, 3710 const struct devlink_param *param, 3711 enum devlink_command cmd) 3712{ 3713 struct devlink_param_item *param_item; 3714 3715 param_item = devlink_param_find_by_name(param_list, param->name); 3716 WARN_ON(!param_item); 3717 devlink_param_notify(devlink, port_index, param_item, cmd); 3718 list_del(&param_item->list); 3719 kfree(param_item); 3720} 3721 3722static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg, 3723 struct netlink_callback *cb) 3724{ 3725 struct devlink_param_item *param_item; 3726 struct devlink_port *devlink_port; 3727 struct devlink *devlink; 3728 int start = cb->args[0]; 3729 int idx = 0; 3730 int err = 0; 3731 3732 mutex_lock(&devlink_mutex); 3733 list_for_each_entry(devlink, &devlink_list, list) { 3734 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3735 continue; 3736 mutex_lock(&devlink->lock); 3737 list_for_each_entry(devlink_port, &devlink->port_list, list) { 3738 list_for_each_entry(param_item, 3739 &devlink_port->param_list, list) { 3740 if (idx < start) { 3741 idx++; 3742 continue; 3743 } 3744 err = devlink_nl_param_fill(msg, 3745 devlink_port->devlink, 3746 devlink_port->index, param_item, 3747 DEVLINK_CMD_PORT_PARAM_GET, 3748 NETLINK_CB(cb->skb).portid, 3749 cb->nlh->nlmsg_seq, 3750 NLM_F_MULTI); 3751 if (err == -EOPNOTSUPP) { 3752 err = 0; 3753 } else if (err) { 3754 mutex_unlock(&devlink->lock); 3755 goto out; 3756 } 3757 idx++; 3758 } 3759 } 3760 mutex_unlock(&devlink->lock); 3761 } 3762out: 3763 mutex_unlock(&devlink_mutex); 3764 3765 if (err != -EMSGSIZE) 3766 return err; 3767 3768 cb->args[0] = idx; 3769 return msg->len; 3770} 3771 3772static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb, 3773 struct genl_info *info) 3774{ 3775 struct devlink_port *devlink_port = info->user_ptr[0]; 3776 struct devlink_param_item *param_item; 3777 struct sk_buff *msg; 3778 int err; 3779 3780 param_item = devlink_param_get_from_info(&devlink_port->param_list, 3781 info); 3782 if (!param_item) 3783 return -EINVAL; 3784 3785 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3786 if (!msg) 3787 return -ENOMEM; 3788 3789 err = devlink_nl_param_fill(msg, devlink_port->devlink, 3790 devlink_port->index, param_item, 3791 DEVLINK_CMD_PORT_PARAM_GET, 3792 info->snd_portid, info->snd_seq, 0); 3793 if (err) { 3794 nlmsg_free(msg); 3795 return err; 3796 } 3797 3798 return genlmsg_reply(msg, info); 3799} 3800 3801static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb, 3802 struct genl_info *info) 3803{ 3804 struct devlink_port *devlink_port = info->user_ptr[0]; 3805 3806 return __devlink_nl_cmd_param_set_doit(devlink_port->devlink, 3807 devlink_port->index, 3808 &devlink_port->param_list, info, 3809 DEVLINK_CMD_PORT_PARAM_NEW); 3810} 3811 3812static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 3813 struct devlink *devlink, 3814 struct devlink_snapshot *snapshot) 3815{ 3816 struct nlattr *snap_attr; 3817 int err; 3818 3819 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 3820 if (!snap_attr) 3821 return -EINVAL; 3822 3823 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 3824 if (err) 3825 goto nla_put_failure; 3826 3827 nla_nest_end(msg, snap_attr); 3828 return 0; 3829 3830nla_put_failure: 3831 nla_nest_cancel(msg, snap_attr); 3832 return err; 3833} 3834 3835static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 3836 struct devlink *devlink, 3837 struct devlink_region *region) 3838{ 3839 struct devlink_snapshot *snapshot; 3840 struct nlattr *snapshots_attr; 3841 int err; 3842 3843 snapshots_attr = nla_nest_start_noflag(msg, 3844 DEVLINK_ATTR_REGION_SNAPSHOTS); 3845 if (!snapshots_attr) 3846 return -EINVAL; 3847 3848 list_for_each_entry(snapshot, &region->snapshot_list, list) { 3849 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 3850 if (err) 3851 goto nla_put_failure; 3852 } 3853 3854 nla_nest_end(msg, snapshots_attr); 3855 return 0; 3856 3857nla_put_failure: 3858 nla_nest_cancel(msg, snapshots_attr); 3859 return err; 3860} 3861 3862static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 3863 enum devlink_command cmd, u32 portid, 3864 u32 seq, int flags, 3865 struct devlink_region *region) 3866{ 3867 void *hdr; 3868 int err; 3869 3870 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3871 if (!hdr) 3872 return -EMSGSIZE; 3873 3874 err = devlink_nl_put_handle(msg, devlink); 3875 if (err) 3876 goto nla_put_failure; 3877 3878 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name); 3879 if (err) 3880 goto nla_put_failure; 3881 3882 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3883 region->size, 3884 DEVLINK_ATTR_PAD); 3885 if (err) 3886 goto nla_put_failure; 3887 3888 err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 3889 if (err) 3890 goto nla_put_failure; 3891 3892 genlmsg_end(msg, hdr); 3893 return 0; 3894 3895nla_put_failure: 3896 genlmsg_cancel(msg, hdr); 3897 return err; 3898} 3899 3900static struct sk_buff * 3901devlink_nl_region_notify_build(struct devlink_region *region, 3902 struct devlink_snapshot *snapshot, 3903 enum devlink_command cmd, u32 portid, u32 seq) 3904{ 3905 struct devlink *devlink = region->devlink; 3906 struct sk_buff *msg; 3907 void *hdr; 3908 int err; 3909 3910 3911 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3912 if (!msg) 3913 return ERR_PTR(-ENOMEM); 3914 3915 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd); 3916 if (!hdr) { 3917 err = -EMSGSIZE; 3918 goto out_free_msg; 3919 } 3920 3921 err = devlink_nl_put_handle(msg, devlink); 3922 if (err) 3923 goto out_cancel_msg; 3924 3925 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 3926 region->ops->name); 3927 if (err) 3928 goto out_cancel_msg; 3929 3930 if (snapshot) { 3931 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 3932 snapshot->id); 3933 if (err) 3934 goto out_cancel_msg; 3935 } else { 3936 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3937 region->size, DEVLINK_ATTR_PAD); 3938 if (err) 3939 goto out_cancel_msg; 3940 } 3941 genlmsg_end(msg, hdr); 3942 3943 return msg; 3944 3945out_cancel_msg: 3946 genlmsg_cancel(msg, hdr); 3947out_free_msg: 3948 nlmsg_free(msg); 3949 return ERR_PTR(err); 3950} 3951 3952static void devlink_nl_region_notify(struct devlink_region *region, 3953 struct devlink_snapshot *snapshot, 3954 enum devlink_command cmd) 3955{ 3956 struct devlink *devlink = region->devlink; 3957 struct sk_buff *msg; 3958 3959 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3960 3961 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0); 3962 if (IS_ERR(msg)) 3963 return; 3964 3965 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3966 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3967} 3968 3969/** 3970 * __devlink_snapshot_id_increment - Increment number of snapshots using an id 3971 * @devlink: devlink instance 3972 * @id: the snapshot id 3973 * 3974 * Track when a new snapshot begins using an id. Load the count for the 3975 * given id from the snapshot xarray, increment it, and store it back. 3976 * 3977 * Called when a new snapshot is created with the given id. 3978 * 3979 * The id *must* have been previously allocated by 3980 * devlink_region_snapshot_id_get(). 3981 * 3982 * Returns 0 on success, or an error on failure. 3983 */ 3984static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id) 3985{ 3986 unsigned long count; 3987 void *p; 3988 3989 lockdep_assert_held(&devlink->lock); 3990 3991 p = xa_load(&devlink->snapshot_ids, id); 3992 if (WARN_ON(!p)) 3993 return -EINVAL; 3994 3995 if (WARN_ON(!xa_is_value(p))) 3996 return -EINVAL; 3997 3998 count = xa_to_value(p); 3999 count++; 4000 4001 return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), 4002 GFP_KERNEL)); 4003} 4004 4005/** 4006 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id 4007 * @devlink: devlink instance 4008 * @id: the snapshot id 4009 * 4010 * Track when a snapshot is deleted and stops using an id. Load the count 4011 * for the given id from the snapshot xarray, decrement it, and store it 4012 * back. 4013 * 4014 * If the count reaches zero, erase this id from the xarray, freeing it 4015 * up for future re-use by devlink_region_snapshot_id_get(). 4016 * 4017 * Called when a snapshot using the given id is deleted, and when the 4018 * initial allocator of the id is finished using it. 4019 */ 4020static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id) 4021{ 4022 unsigned long count; 4023 void *p; 4024 4025 lockdep_assert_held(&devlink->lock); 4026 4027 p = xa_load(&devlink->snapshot_ids, id); 4028 if (WARN_ON(!p)) 4029 return; 4030 4031 if (WARN_ON(!xa_is_value(p))) 4032 return; 4033 4034 count = xa_to_value(p); 4035 4036 if (count > 1) { 4037 count--; 4038 xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), 4039 GFP_KERNEL); 4040 } else { 4041 /* If this was the last user, we can erase this id */ 4042 xa_erase(&devlink->snapshot_ids, id); 4043 } 4044} 4045 4046/** 4047 * __devlink_snapshot_id_insert - Insert a specific snapshot ID 4048 * @devlink: devlink instance 4049 * @id: the snapshot id 4050 * 4051 * Mark the given snapshot id as used by inserting a zero value into the 4052 * snapshot xarray. 4053 * 4054 * This must be called while holding the devlink instance lock. Unlike 4055 * devlink_snapshot_id_get, the initial reference count is zero, not one. 4056 * It is expected that the id will immediately be used before 4057 * releasing the devlink instance lock. 4058 * 4059 * Returns zero on success, or an error code if the snapshot id could not 4060 * be inserted. 4061 */ 4062static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id) 4063{ 4064 lockdep_assert_held(&devlink->lock); 4065 4066 if (xa_load(&devlink->snapshot_ids, id)) 4067 return -EEXIST; 4068 4069 return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(0), 4070 GFP_KERNEL)); 4071} 4072 4073/** 4074 * __devlink_region_snapshot_id_get - get snapshot ID 4075 * @devlink: devlink instance 4076 * @id: storage to return snapshot id 4077 * 4078 * Allocates a new snapshot id. Returns zero on success, or a negative 4079 * error on failure. Must be called while holding the devlink instance 4080 * lock. 4081 * 4082 * Snapshot IDs are tracked using an xarray which stores the number of 4083 * users of the snapshot id. 4084 * 4085 * Note that the caller of this function counts as a 'user', in order to 4086 * avoid race conditions. The caller must release its hold on the 4087 * snapshot by using devlink_region_snapshot_id_put. 4088 */ 4089static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) 4090{ 4091 lockdep_assert_held(&devlink->lock); 4092 4093 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1), 4094 xa_limit_32b, GFP_KERNEL); 4095} 4096 4097/** 4098 * __devlink_region_snapshot_create - create a new snapshot 4099 * This will add a new snapshot of a region. The snapshot 4100 * will be stored on the region struct and can be accessed 4101 * from devlink. This is useful for future analyses of snapshots. 4102 * Multiple snapshots can be created on a region. 4103 * The @snapshot_id should be obtained using the getter function. 4104 * 4105 * Must be called only while holding the devlink instance lock. 4106 * 4107 * @region: devlink region of the snapshot 4108 * @data: snapshot data 4109 * @snapshot_id: snapshot id to be created 4110 */ 4111static int 4112__devlink_region_snapshot_create(struct devlink_region *region, 4113 u8 *data, u32 snapshot_id) 4114{ 4115 struct devlink *devlink = region->devlink; 4116 struct devlink_snapshot *snapshot; 4117 int err; 4118 4119 lockdep_assert_held(&devlink->lock); 4120 4121 /* check if region can hold one more snapshot */ 4122 if (region->cur_snapshots == region->max_snapshots) 4123 return -ENOSPC; 4124 4125 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) 4126 return -EEXIST; 4127 4128 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 4129 if (!snapshot) 4130 return -ENOMEM; 4131 4132 err = __devlink_snapshot_id_increment(devlink, snapshot_id); 4133 if (err) 4134 goto err_snapshot_id_increment; 4135 4136 snapshot->id = snapshot_id; 4137 snapshot->region = region; 4138 snapshot->data = data; 4139 4140 list_add_tail(&snapshot->list, &region->snapshot_list); 4141 4142 region->cur_snapshots++; 4143 4144 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 4145 return 0; 4146 4147err_snapshot_id_increment: 4148 kfree(snapshot); 4149 return err; 4150} 4151 4152static void devlink_region_snapshot_del(struct devlink_region *region, 4153 struct devlink_snapshot *snapshot) 4154{ 4155 struct devlink *devlink = region->devlink; 4156 4157 lockdep_assert_held(&devlink->lock); 4158 4159 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 4160 region->cur_snapshots--; 4161 list_del(&snapshot->list); 4162 region->ops->destructor(snapshot->data); 4163 __devlink_snapshot_id_decrement(devlink, snapshot->id); 4164 kfree(snapshot); 4165} 4166 4167static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb, 4168 struct genl_info *info) 4169{ 4170 struct devlink *devlink = info->user_ptr[0]; 4171 struct devlink_region *region; 4172 const char *region_name; 4173 struct sk_buff *msg; 4174 int err; 4175 4176 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) 4177 return -EINVAL; 4178 4179 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 4180 region = devlink_region_get_by_name(devlink, region_name); 4181 if (!region) 4182 return -EINVAL; 4183 4184 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4185 if (!msg) 4186 return -ENOMEM; 4187 4188 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 4189 info->snd_portid, info->snd_seq, 0, 4190 region); 4191 if (err) { 4192 nlmsg_free(msg); 4193 return err; 4194 } 4195 4196 return genlmsg_reply(msg, info); 4197} 4198 4199static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, 4200 struct netlink_callback *cb) 4201{ 4202 struct devlink_region *region; 4203 struct devlink *devlink; 4204 int start = cb->args[0]; 4205 int idx = 0; 4206 int err; 4207 4208 mutex_lock(&devlink_mutex); 4209 list_for_each_entry(devlink, &devlink_list, list) { 4210 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 4211 continue; 4212 4213 mutex_lock(&devlink->lock); 4214 list_for_each_entry(region, &devlink->region_list, list) { 4215 if (idx < start) { 4216 idx++; 4217 continue; 4218 } 4219 err = devlink_nl_region_fill(msg, devlink, 4220 DEVLINK_CMD_REGION_GET, 4221 NETLINK_CB(cb->skb).portid, 4222 cb->nlh->nlmsg_seq, 4223 NLM_F_MULTI, region); 4224 if (err) { 4225 mutex_unlock(&devlink->lock); 4226 goto out; 4227 } 4228 idx++; 4229 } 4230 mutex_unlock(&devlink->lock); 4231 } 4232out: 4233 mutex_unlock(&devlink_mutex); 4234 cb->args[0] = idx; 4235 return msg->len; 4236} 4237 4238static int devlink_nl_cmd_region_del(struct sk_buff *skb, 4239 struct genl_info *info) 4240{ 4241 struct devlink *devlink = info->user_ptr[0]; 4242 struct devlink_snapshot *snapshot; 4243 struct devlink_region *region; 4244 const char *region_name; 4245 u32 snapshot_id; 4246 4247 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] || 4248 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 4249 return -EINVAL; 4250 4251 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 4252 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 4253 4254 region = devlink_region_get_by_name(devlink, region_name); 4255 if (!region) 4256 return -EINVAL; 4257 4258 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 4259 if (!snapshot) 4260 return -EINVAL; 4261 4262 devlink_region_snapshot_del(region, snapshot); 4263 return 0; 4264} 4265 4266static int 4267devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) 4268{ 4269 struct devlink *devlink = info->user_ptr[0]; 4270 struct devlink_snapshot *snapshot; 4271 struct nlattr *snapshot_id_attr; 4272 struct devlink_region *region; 4273 const char *region_name; 4274 u32 snapshot_id; 4275 u8 *data; 4276 int err; 4277 4278 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) { 4279 NL_SET_ERR_MSG_MOD(info->extack, "No region name provided"); 4280 return -EINVAL; 4281 } 4282 4283 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 4284 region = devlink_region_get_by_name(devlink, region_name); 4285 if (!region) { 4286 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not exist"); 4287 return -EINVAL; 4288 } 4289 4290 if (!region->ops->snapshot) { 4291 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not support taking an immediate snapshot"); 4292 return -EOPNOTSUPP; 4293 } 4294 4295 if (region->cur_snapshots == region->max_snapshots) { 4296 NL_SET_ERR_MSG_MOD(info->extack, "The region has reached the maximum number of stored snapshots"); 4297 return -ENOSPC; 4298 } 4299 4300 snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; 4301 if (snapshot_id_attr) { 4302 snapshot_id = nla_get_u32(snapshot_id_attr); 4303 4304 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4305 NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use"); 4306 return -EEXIST; 4307 } 4308 4309 err = __devlink_snapshot_id_insert(devlink, snapshot_id); 4310 if (err) 4311 return err; 4312 } else { 4313 err = __devlink_region_snapshot_id_get(devlink, &snapshot_id); 4314 if (err) { 4315 NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id"); 4316 return err; 4317 } 4318 } 4319 4320 err = region->ops->snapshot(devlink, info->extack, &data); 4321 if (err) 4322 goto err_snapshot_capture; 4323 4324 err = __devlink_region_snapshot_create(region, data, snapshot_id); 4325 if (err) 4326 goto err_snapshot_create; 4327 4328 if (!snapshot_id_attr) { 4329 struct sk_buff *msg; 4330 4331 snapshot = devlink_region_snapshot_get_by_id(region, 4332 snapshot_id); 4333 if (WARN_ON(!snapshot)) 4334 return -EINVAL; 4335 4336 msg = devlink_nl_region_notify_build(region, snapshot, 4337 DEVLINK_CMD_REGION_NEW, 4338 info->snd_portid, 4339 info->snd_seq); 4340 err = PTR_ERR_OR_ZERO(msg); 4341 if (err) 4342 goto err_notify; 4343 4344 err = genlmsg_reply(msg, info); 4345 if (err) 4346 goto err_notify; 4347 } 4348 4349 return 0; 4350 4351err_snapshot_create: 4352 region->ops->destructor(data); 4353err_snapshot_capture: 4354 __devlink_snapshot_id_decrement(devlink, snapshot_id); 4355 return err; 4356 4357err_notify: 4358 devlink_region_snapshot_del(region, snapshot); 4359 return err; 4360} 4361 4362static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 4363 struct devlink *devlink, 4364 u8 *chunk, u32 chunk_size, 4365 u64 addr) 4366{ 4367 struct nlattr *chunk_attr; 4368 int err; 4369 4370 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK); 4371 if (!chunk_attr) 4372 return -EINVAL; 4373 4374 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 4375 if (err) 4376 goto nla_put_failure; 4377 4378 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 4379 DEVLINK_ATTR_PAD); 4380 if (err) 4381 goto nla_put_failure; 4382 4383 nla_nest_end(msg, chunk_attr); 4384 return 0; 4385 4386nla_put_failure: 4387 nla_nest_cancel(msg, chunk_attr); 4388 return err; 4389} 4390 4391#define DEVLINK_REGION_READ_CHUNK_SIZE 256 4392 4393static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, 4394 struct devlink *devlink, 4395 struct devlink_region *region, 4396 struct nlattr **attrs, 4397 u64 start_offset, 4398 u64 end_offset, 4399 u64 *new_offset) 4400{ 4401 struct devlink_snapshot *snapshot; 4402 u64 curr_offset = start_offset; 4403 u32 snapshot_id; 4404 int err = 0; 4405 4406 *new_offset = start_offset; 4407 4408 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 4409 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 4410 if (!snapshot) 4411 return -EINVAL; 4412 4413 while (curr_offset < end_offset) { 4414 u32 data_size; 4415 u8 *data; 4416 4417 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) 4418 data_size = end_offset - curr_offset; 4419 else 4420 data_size = DEVLINK_REGION_READ_CHUNK_SIZE; 4421 4422 data = &snapshot->data[curr_offset]; 4423 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, 4424 data, data_size, 4425 curr_offset); 4426 if (err) 4427 break; 4428 4429 curr_offset += data_size; 4430 } 4431 *new_offset = curr_offset; 4432 4433 return err; 4434} 4435 4436static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 4437 struct netlink_callback *cb) 4438{ 4439 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 4440 u64 ret_offset, start_offset, end_offset = U64_MAX; 4441 struct nlattr **attrs = info->attrs; 4442 struct devlink_region *region; 4443 struct nlattr *chunks_attr; 4444 const char *region_name; 4445 struct devlink *devlink; 4446 void *hdr; 4447 int err; 4448 4449 start_offset = *((u64 *)&cb->args[0]); 4450 4451 mutex_lock(&devlink_mutex); 4452 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 4453 if (IS_ERR(devlink)) { 4454 err = PTR_ERR(devlink); 4455 goto out_dev; 4456 } 4457 4458 mutex_lock(&devlink->lock); 4459 4460 if (!attrs[DEVLINK_ATTR_REGION_NAME] || 4461 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { 4462 err = -EINVAL; 4463 goto out_unlock; 4464 } 4465 4466 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); 4467 region = devlink_region_get_by_name(devlink, region_name); 4468 if (!region) { 4469 err = -EINVAL; 4470 goto out_unlock; 4471 } 4472 4473 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 4474 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 4475 if (!start_offset) 4476 start_offset = 4477 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 4478 4479 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 4480 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 4481 } 4482 4483 if (end_offset > region->size) 4484 end_offset = region->size; 4485 4486 /* return 0 if there is no further data to read */ 4487 if (start_offset == end_offset) { 4488 err = 0; 4489 goto out_unlock; 4490 } 4491 4492 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 4493 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 4494 DEVLINK_CMD_REGION_READ); 4495 if (!hdr) { 4496 err = -EMSGSIZE; 4497 goto out_unlock; 4498 } 4499 4500 err = devlink_nl_put_handle(skb, devlink); 4501 if (err) 4502 goto nla_put_failure; 4503 4504 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 4505 if (err) 4506 goto nla_put_failure; 4507 4508 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS); 4509 if (!chunks_attr) { 4510 err = -EMSGSIZE; 4511 goto nla_put_failure; 4512 } 4513 4514 err = devlink_nl_region_read_snapshot_fill(skb, devlink, 4515 region, attrs, 4516 start_offset, 4517 end_offset, &ret_offset); 4518 4519 if (err && err != -EMSGSIZE) 4520 goto nla_put_failure; 4521 4522 /* Check if there was any progress done to prevent infinite loop */ 4523 if (ret_offset == start_offset) { 4524 err = -EINVAL; 4525 goto nla_put_failure; 4526 } 4527 4528 *((u64 *)&cb->args[0]) = ret_offset; 4529 4530 nla_nest_end(skb, chunks_attr); 4531 genlmsg_end(skb, hdr); 4532 mutex_unlock(&devlink->lock); 4533 mutex_unlock(&devlink_mutex); 4534 4535 return skb->len; 4536 4537nla_put_failure: 4538 genlmsg_cancel(skb, hdr); 4539out_unlock: 4540 mutex_unlock(&devlink->lock); 4541out_dev: 4542 mutex_unlock(&devlink_mutex); 4543 return err; 4544} 4545 4546struct devlink_info_req { 4547 struct sk_buff *msg; 4548}; 4549 4550int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name) 4551{ 4552 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name); 4553} 4554EXPORT_SYMBOL_GPL(devlink_info_driver_name_put); 4555 4556int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn) 4557{ 4558 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn); 4559} 4560EXPORT_SYMBOL_GPL(devlink_info_serial_number_put); 4561 4562int devlink_info_board_serial_number_put(struct devlink_info_req *req, 4563 const char *bsn) 4564{ 4565 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER, 4566 bsn); 4567} 4568EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put); 4569 4570static int devlink_info_version_put(struct devlink_info_req *req, int attr, 4571 const char *version_name, 4572 const char *version_value) 4573{ 4574 struct nlattr *nest; 4575 int err; 4576 4577 nest = nla_nest_start_noflag(req->msg, attr); 4578 if (!nest) 4579 return -EMSGSIZE; 4580 4581 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME, 4582 version_name); 4583 if (err) 4584 goto nla_put_failure; 4585 4586 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE, 4587 version_value); 4588 if (err) 4589 goto nla_put_failure; 4590 4591 nla_nest_end(req->msg, nest); 4592 4593 return 0; 4594 4595nla_put_failure: 4596 nla_nest_cancel(req->msg, nest); 4597 return err; 4598} 4599 4600int devlink_info_version_fixed_put(struct devlink_info_req *req, 4601 const char *version_name, 4602 const char *version_value) 4603{ 4604 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED, 4605 version_name, version_value); 4606} 4607EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put); 4608 4609int devlink_info_version_stored_put(struct devlink_info_req *req, 4610 const char *version_name, 4611 const char *version_value) 4612{ 4613 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED, 4614 version_name, version_value); 4615} 4616EXPORT_SYMBOL_GPL(devlink_info_version_stored_put); 4617 4618int devlink_info_version_running_put(struct devlink_info_req *req, 4619 const char *version_name, 4620 const char *version_value) 4621{ 4622 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING, 4623 version_name, version_value); 4624} 4625EXPORT_SYMBOL_GPL(devlink_info_version_running_put); 4626 4627static int 4628devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink, 4629 enum devlink_command cmd, u32 portid, 4630 u32 seq, int flags, struct netlink_ext_ack *extack) 4631{ 4632 struct devlink_info_req req; 4633 void *hdr; 4634 int err; 4635 4636 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 4637 if (!hdr) 4638 return -EMSGSIZE; 4639 4640 err = -EMSGSIZE; 4641 if (devlink_nl_put_handle(msg, devlink)) 4642 goto err_cancel_msg; 4643 4644 req.msg = msg; 4645 err = devlink->ops->info_get(devlink, &req, extack); 4646 if (err) 4647 goto err_cancel_msg; 4648 4649 genlmsg_end(msg, hdr); 4650 return 0; 4651 4652err_cancel_msg: 4653 genlmsg_cancel(msg, hdr); 4654 return err; 4655} 4656 4657static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb, 4658 struct genl_info *info) 4659{ 4660 struct devlink *devlink = info->user_ptr[0]; 4661 struct sk_buff *msg; 4662 int err; 4663 4664 if (!devlink->ops->info_get) 4665 return -EOPNOTSUPP; 4666 4667 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4668 if (!msg) 4669 return -ENOMEM; 4670 4671 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, 4672 info->snd_portid, info->snd_seq, 0, 4673 info->extack); 4674 if (err) { 4675 nlmsg_free(msg); 4676 return err; 4677 } 4678 4679 return genlmsg_reply(msg, info); 4680} 4681 4682static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg, 4683 struct netlink_callback *cb) 4684{ 4685 struct devlink *devlink; 4686 int start = cb->args[0]; 4687 int idx = 0; 4688 int err = 0; 4689 4690 mutex_lock(&devlink_mutex); 4691 list_for_each_entry(devlink, &devlink_list, list) { 4692 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 4693 continue; 4694 if (idx < start) { 4695 idx++; 4696 continue; 4697 } 4698 4699 if (!devlink->ops->info_get) { 4700 idx++; 4701 continue; 4702 } 4703 4704 mutex_lock(&devlink->lock); 4705 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, 4706 NETLINK_CB(cb->skb).portid, 4707 cb->nlh->nlmsg_seq, NLM_F_MULTI, 4708 cb->extack); 4709 mutex_unlock(&devlink->lock); 4710 if (err == -EOPNOTSUPP) 4711 err = 0; 4712 else if (err) 4713 break; 4714 idx++; 4715 } 4716 mutex_unlock(&devlink_mutex); 4717 4718 if (err != -EMSGSIZE) 4719 return err; 4720 4721 cb->args[0] = idx; 4722 return msg->len; 4723} 4724 4725struct devlink_fmsg_item { 4726 struct list_head list; 4727 int attrtype; 4728 u8 nla_type; 4729 u16 len; 4730 int value[]; 4731}; 4732 4733struct devlink_fmsg { 4734 struct list_head item_list; 4735 bool putting_binary; /* This flag forces enclosing of binary data 4736 * in an array brackets. It forces using 4737 * of designated API: 4738 * devlink_fmsg_binary_pair_nest_start() 4739 * devlink_fmsg_binary_pair_nest_end() 4740 */ 4741}; 4742 4743static struct devlink_fmsg *devlink_fmsg_alloc(void) 4744{ 4745 struct devlink_fmsg *fmsg; 4746 4747 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL); 4748 if (!fmsg) 4749 return NULL; 4750 4751 INIT_LIST_HEAD(&fmsg->item_list); 4752 4753 return fmsg; 4754} 4755 4756static void devlink_fmsg_free(struct devlink_fmsg *fmsg) 4757{ 4758 struct devlink_fmsg_item *item, *tmp; 4759 4760 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) { 4761 list_del(&item->list); 4762 kfree(item); 4763 } 4764 kfree(fmsg); 4765} 4766 4767static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg, 4768 int attrtype) 4769{ 4770 struct devlink_fmsg_item *item; 4771 4772 item = kzalloc(sizeof(*item), GFP_KERNEL); 4773 if (!item) 4774 return -ENOMEM; 4775 4776 item->attrtype = attrtype; 4777 list_add_tail(&item->list, &fmsg->item_list); 4778 4779 return 0; 4780} 4781 4782int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg) 4783{ 4784 if (fmsg->putting_binary) 4785 return -EINVAL; 4786 4787 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START); 4788} 4789EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start); 4790 4791static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg) 4792{ 4793 if (fmsg->putting_binary) 4794 return -EINVAL; 4795 4796 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END); 4797} 4798 4799int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg) 4800{ 4801 if (fmsg->putting_binary) 4802 return -EINVAL; 4803 4804 return devlink_fmsg_nest_end(fmsg); 4805} 4806EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end); 4807 4808#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN) 4809 4810static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name) 4811{ 4812 struct devlink_fmsg_item *item; 4813 4814 if (fmsg->putting_binary) 4815 return -EINVAL; 4816 4817 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE) 4818 return -EMSGSIZE; 4819 4820 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL); 4821 if (!item) 4822 return -ENOMEM; 4823 4824 item->nla_type = NLA_NUL_STRING; 4825 item->len = strlen(name) + 1; 4826 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME; 4827 memcpy(&item->value, name, item->len); 4828 list_add_tail(&item->list, &fmsg->item_list); 4829 4830 return 0; 4831} 4832 4833int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name) 4834{ 4835 int err; 4836 4837 if (fmsg->putting_binary) 4838 return -EINVAL; 4839 4840 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START); 4841 if (err) 4842 return err; 4843 4844 err = devlink_fmsg_put_name(fmsg, name); 4845 if (err) 4846 return err; 4847 4848 return 0; 4849} 4850EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start); 4851 4852int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg) 4853{ 4854 if (fmsg->putting_binary) 4855 return -EINVAL; 4856 4857 return devlink_fmsg_nest_end(fmsg); 4858} 4859EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end); 4860 4861int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg, 4862 const char *name) 4863{ 4864 int err; 4865 4866 if (fmsg->putting_binary) 4867 return -EINVAL; 4868 4869 err = devlink_fmsg_pair_nest_start(fmsg, name); 4870 if (err) 4871 return err; 4872 4873 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START); 4874 if (err) 4875 return err; 4876 4877 return 0; 4878} 4879EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start); 4880 4881int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg) 4882{ 4883 int err; 4884 4885 if (fmsg->putting_binary) 4886 return -EINVAL; 4887 4888 err = devlink_fmsg_nest_end(fmsg); 4889 if (err) 4890 return err; 4891 4892 err = devlink_fmsg_nest_end(fmsg); 4893 if (err) 4894 return err; 4895 4896 return 0; 4897} 4898EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end); 4899 4900int devlink_fmsg_binary_pair_nest_start(struct devlink_fmsg *fmsg, 4901 const char *name) 4902{ 4903 int err; 4904 4905 err = devlink_fmsg_arr_pair_nest_start(fmsg, name); 4906 if (err) 4907 return err; 4908 4909 fmsg->putting_binary = true; 4910 return err; 4911} 4912EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_start); 4913 4914int devlink_fmsg_binary_pair_nest_end(struct devlink_fmsg *fmsg) 4915{ 4916 if (!fmsg->putting_binary) 4917 return -EINVAL; 4918 4919 fmsg->putting_binary = false; 4920 return devlink_fmsg_arr_pair_nest_end(fmsg); 4921} 4922EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_end); 4923 4924static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg, 4925 const void *value, u16 value_len, 4926 u8 value_nla_type) 4927{ 4928 struct devlink_fmsg_item *item; 4929 4930 if (value_len > DEVLINK_FMSG_MAX_SIZE) 4931 return -EMSGSIZE; 4932 4933 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL); 4934 if (!item) 4935 return -ENOMEM; 4936 4937 item->nla_type = value_nla_type; 4938 item->len = value_len; 4939 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA; 4940 memcpy(&item->value, value, item->len); 4941 list_add_tail(&item->list, &fmsg->item_list); 4942 4943 return 0; 4944} 4945 4946int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value) 4947{ 4948 if (fmsg->putting_binary) 4949 return -EINVAL; 4950 4951 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG); 4952} 4953EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put); 4954 4955int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value) 4956{ 4957 if (fmsg->putting_binary) 4958 return -EINVAL; 4959 4960 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8); 4961} 4962EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put); 4963 4964int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value) 4965{ 4966 if (fmsg->putting_binary) 4967 return -EINVAL; 4968 4969 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32); 4970} 4971EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put); 4972 4973int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value) 4974{ 4975 if (fmsg->putting_binary) 4976 return -EINVAL; 4977 4978 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64); 4979} 4980EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put); 4981 4982int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value) 4983{ 4984 if (fmsg->putting_binary) 4985 return -EINVAL; 4986 4987 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1, 4988 NLA_NUL_STRING); 4989} 4990EXPORT_SYMBOL_GPL(devlink_fmsg_string_put); 4991 4992int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value, 4993 u16 value_len) 4994{ 4995 if (!fmsg->putting_binary) 4996 return -EINVAL; 4997 4998 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY); 4999} 5000EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put); 5001 5002int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name, 5003 bool value) 5004{ 5005 int err; 5006 5007 err = devlink_fmsg_pair_nest_start(fmsg, name); 5008 if (err) 5009 return err; 5010 5011 err = devlink_fmsg_bool_put(fmsg, value); 5012 if (err) 5013 return err; 5014 5015 err = devlink_fmsg_pair_nest_end(fmsg); 5016 if (err) 5017 return err; 5018 5019 return 0; 5020} 5021EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put); 5022 5023int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name, 5024 u8 value) 5025{ 5026 int err; 5027 5028 err = devlink_fmsg_pair_nest_start(fmsg, name); 5029 if (err) 5030 return err; 5031 5032 err = devlink_fmsg_u8_put(fmsg, value); 5033 if (err) 5034 return err; 5035 5036 err = devlink_fmsg_pair_nest_end(fmsg); 5037 if (err) 5038 return err; 5039 5040 return 0; 5041} 5042EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put); 5043 5044int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name, 5045 u32 value) 5046{ 5047 int err; 5048 5049 err = devlink_fmsg_pair_nest_start(fmsg, name); 5050 if (err) 5051 return err; 5052 5053 err = devlink_fmsg_u32_put(fmsg, value); 5054 if (err) 5055 return err; 5056 5057 err = devlink_fmsg_pair_nest_end(fmsg); 5058 if (err) 5059 return err; 5060 5061 return 0; 5062} 5063EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put); 5064 5065int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name, 5066 u64 value) 5067{ 5068 int err; 5069 5070 err = devlink_fmsg_pair_nest_start(fmsg, name); 5071 if (err) 5072 return err; 5073 5074 err = devlink_fmsg_u64_put(fmsg, value); 5075 if (err) 5076 return err; 5077 5078 err = devlink_fmsg_pair_nest_end(fmsg); 5079 if (err) 5080 return err; 5081 5082 return 0; 5083} 5084EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put); 5085 5086int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name, 5087 const char *value) 5088{ 5089 int err; 5090 5091 err = devlink_fmsg_pair_nest_start(fmsg, name); 5092 if (err) 5093 return err; 5094 5095 err = devlink_fmsg_string_put(fmsg, value); 5096 if (err) 5097 return err; 5098 5099 err = devlink_fmsg_pair_nest_end(fmsg); 5100 if (err) 5101 return err; 5102 5103 return 0; 5104} 5105EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put); 5106 5107int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name, 5108 const void *value, u32 value_len) 5109{ 5110 u32 data_size; 5111 int end_err; 5112 u32 offset; 5113 int err; 5114 5115 err = devlink_fmsg_binary_pair_nest_start(fmsg, name); 5116 if (err) 5117 return err; 5118 5119 for (offset = 0; offset < value_len; offset += data_size) { 5120 data_size = value_len - offset; 5121 if (data_size > DEVLINK_FMSG_MAX_SIZE) 5122 data_size = DEVLINK_FMSG_MAX_SIZE; 5123 err = devlink_fmsg_binary_put(fmsg, value + offset, data_size); 5124 if (err) 5125 break; 5126 /* Exit from loop with a break (instead of 5127 * return) to make sure putting_binary is turned off in 5128 * devlink_fmsg_binary_pair_nest_end 5129 */ 5130 } 5131 5132 end_err = devlink_fmsg_binary_pair_nest_end(fmsg); 5133 if (end_err) 5134 err = end_err; 5135 5136 return err; 5137} 5138EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put); 5139 5140static int 5141devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb) 5142{ 5143 switch (msg->nla_type) { 5144 case NLA_FLAG: 5145 case NLA_U8: 5146 case NLA_U32: 5147 case NLA_U64: 5148 case NLA_NUL_STRING: 5149 case NLA_BINARY: 5150 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, 5151 msg->nla_type); 5152 default: 5153 return -EINVAL; 5154 } 5155} 5156 5157static int 5158devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb) 5159{ 5160 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA; 5161 u8 tmp; 5162 5163 switch (msg->nla_type) { 5164 case NLA_FLAG: 5165 /* Always provide flag data, regardless of its value */ 5166 tmp = *(bool *) msg->value; 5167 5168 return nla_put_u8(skb, attrtype, tmp); 5169 case NLA_U8: 5170 return nla_put_u8(skb, attrtype, *(u8 *) msg->value); 5171 case NLA_U32: 5172 return nla_put_u32(skb, attrtype, *(u32 *) msg->value); 5173 case NLA_U64: 5174 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value, 5175 DEVLINK_ATTR_PAD); 5176 case NLA_NUL_STRING: 5177 return nla_put_string(skb, attrtype, (char *) &msg->value); 5178 case NLA_BINARY: 5179 return nla_put(skb, attrtype, msg->len, (void *) &msg->value); 5180 default: 5181 return -EINVAL; 5182 } 5183} 5184 5185static int 5186devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb, 5187 int *start) 5188{ 5189 struct devlink_fmsg_item *item; 5190 struct nlattr *fmsg_nlattr; 5191 int i = 0; 5192 int err; 5193 5194 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG); 5195 if (!fmsg_nlattr) 5196 return -EMSGSIZE; 5197 5198 list_for_each_entry(item, &fmsg->item_list, list) { 5199 if (i < *start) { 5200 i++; 5201 continue; 5202 } 5203 5204 switch (item->attrtype) { 5205 case DEVLINK_ATTR_FMSG_OBJ_NEST_START: 5206 case DEVLINK_ATTR_FMSG_PAIR_NEST_START: 5207 case DEVLINK_ATTR_FMSG_ARR_NEST_START: 5208 case DEVLINK_ATTR_FMSG_NEST_END: 5209 err = nla_put_flag(skb, item->attrtype); 5210 break; 5211 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA: 5212 err = devlink_fmsg_item_fill_type(item, skb); 5213 if (err) 5214 break; 5215 err = devlink_fmsg_item_fill_data(item, skb); 5216 break; 5217 case DEVLINK_ATTR_FMSG_OBJ_NAME: 5218 err = nla_put_string(skb, item->attrtype, 5219 (char *) &item->value); 5220 break; 5221 default: 5222 err = -EINVAL; 5223 break; 5224 } 5225 if (!err) 5226 *start = ++i; 5227 else 5228 break; 5229 } 5230 5231 nla_nest_end(skb, fmsg_nlattr); 5232 return err; 5233} 5234 5235static int devlink_fmsg_snd(struct devlink_fmsg *fmsg, 5236 struct genl_info *info, 5237 enum devlink_command cmd, int flags) 5238{ 5239 struct nlmsghdr *nlh; 5240 struct sk_buff *skb; 5241 bool last = false; 5242 int index = 0; 5243 void *hdr; 5244 int err; 5245 5246 while (!last) { 5247 int tmp_index = index; 5248 5249 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 5250 if (!skb) 5251 return -ENOMEM; 5252 5253 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 5254 &devlink_nl_family, flags | NLM_F_MULTI, cmd); 5255 if (!hdr) { 5256 err = -EMSGSIZE; 5257 goto nla_put_failure; 5258 } 5259 5260 err = devlink_fmsg_prepare_skb(fmsg, skb, &index); 5261 if (!err) 5262 last = true; 5263 else if (err != -EMSGSIZE || tmp_index == index) 5264 goto nla_put_failure; 5265 5266 genlmsg_end(skb, hdr); 5267 err = genlmsg_reply(skb, info); 5268 if (err) 5269 return err; 5270 } 5271 5272 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 5273 if (!skb) 5274 return -ENOMEM; 5275 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 5276 NLMSG_DONE, 0, flags | NLM_F_MULTI); 5277 if (!nlh) { 5278 err = -EMSGSIZE; 5279 goto nla_put_failure; 5280 } 5281 5282 return genlmsg_reply(skb, info); 5283 5284nla_put_failure: 5285 nlmsg_free(skb); 5286 return err; 5287} 5288 5289static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb, 5290 struct netlink_callback *cb, 5291 enum devlink_command cmd) 5292{ 5293 int index = cb->args[0]; 5294 int tmp_index = index; 5295 void *hdr; 5296 int err; 5297 5298 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 5299 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd); 5300 if (!hdr) { 5301 err = -EMSGSIZE; 5302 goto nla_put_failure; 5303 } 5304 5305 err = devlink_fmsg_prepare_skb(fmsg, skb, &index); 5306 if ((err && err != -EMSGSIZE) || tmp_index == index) 5307 goto nla_put_failure; 5308 5309 cb->args[0] = index; 5310 genlmsg_end(skb, hdr); 5311 return skb->len; 5312 5313nla_put_failure: 5314 genlmsg_cancel(skb, hdr); 5315 return err; 5316} 5317 5318struct devlink_health_reporter { 5319 struct list_head list; 5320 void *priv; 5321 const struct devlink_health_reporter_ops *ops; 5322 struct devlink *devlink; 5323 struct devlink_port *devlink_port; 5324 struct devlink_fmsg *dump_fmsg; 5325 struct mutex dump_lock; /* lock parallel read/write from dump buffers */ 5326 u64 graceful_period; 5327 bool auto_recover; 5328 bool auto_dump; 5329 u8 health_state; 5330 u64 dump_ts; 5331 u64 dump_real_ts; 5332 u64 error_count; 5333 u64 recovery_count; 5334 u64 last_recovery_ts; 5335 refcount_t refcount; 5336}; 5337 5338void * 5339devlink_health_reporter_priv(struct devlink_health_reporter *reporter) 5340{ 5341 return reporter->priv; 5342} 5343EXPORT_SYMBOL_GPL(devlink_health_reporter_priv); 5344 5345static struct devlink_health_reporter * 5346__devlink_health_reporter_find_by_name(struct list_head *reporter_list, 5347 struct mutex *list_lock, 5348 const char *reporter_name) 5349{ 5350 struct devlink_health_reporter *reporter; 5351 5352 lockdep_assert_held(list_lock); 5353 list_for_each_entry(reporter, reporter_list, list) 5354 if (!strcmp(reporter->ops->name, reporter_name)) 5355 return reporter; 5356 return NULL; 5357} 5358 5359static struct devlink_health_reporter * 5360devlink_health_reporter_find_by_name(struct devlink *devlink, 5361 const char *reporter_name) 5362{ 5363 return __devlink_health_reporter_find_by_name(&devlink->reporter_list, 5364 &devlink->reporters_lock, 5365 reporter_name); 5366} 5367 5368static struct devlink_health_reporter * 5369devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port, 5370 const char *reporter_name) 5371{ 5372 return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list, 5373 &devlink_port->reporters_lock, 5374 reporter_name); 5375} 5376 5377static struct devlink_health_reporter * 5378__devlink_health_reporter_create(struct devlink *devlink, 5379 const struct devlink_health_reporter_ops *ops, 5380 u64 graceful_period, void *priv) 5381{ 5382 struct devlink_health_reporter *reporter; 5383 5384 if (WARN_ON(graceful_period && !ops->recover)) 5385 return ERR_PTR(-EINVAL); 5386 5387 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL); 5388 if (!reporter) 5389 return ERR_PTR(-ENOMEM); 5390 5391 reporter->priv = priv; 5392 reporter->ops = ops; 5393 reporter->devlink = devlink; 5394 reporter->graceful_period = graceful_period; 5395 reporter->auto_recover = !!ops->recover; 5396 reporter->auto_dump = !!ops->dump; 5397 mutex_init(&reporter->dump_lock); 5398 refcount_set(&reporter->refcount, 1); 5399 return reporter; 5400} 5401 5402/** 5403 * devlink_port_health_reporter_create - create devlink health reporter for 5404 * specified port instance 5405 * 5406 * @port: devlink_port which should contain the new reporter 5407 * @ops: ops 5408 * @graceful_period: to avoid recovery loops, in msecs 5409 * @priv: priv 5410 */ 5411struct devlink_health_reporter * 5412devlink_port_health_reporter_create(struct devlink_port *port, 5413 const struct devlink_health_reporter_ops *ops, 5414 u64 graceful_period, void *priv) 5415{ 5416 struct devlink_health_reporter *reporter; 5417 5418 mutex_lock(&port->reporters_lock); 5419 if (__devlink_health_reporter_find_by_name(&port->reporter_list, 5420 &port->reporters_lock, ops->name)) { 5421 reporter = ERR_PTR(-EEXIST); 5422 goto unlock; 5423 } 5424 5425 reporter = __devlink_health_reporter_create(port->devlink, ops, 5426 graceful_period, priv); 5427 if (IS_ERR(reporter)) 5428 goto unlock; 5429 5430 reporter->devlink_port = port; 5431 list_add_tail(&reporter->list, &port->reporter_list); 5432unlock: 5433 mutex_unlock(&port->reporters_lock); 5434 return reporter; 5435} 5436EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create); 5437 5438/** 5439 * devlink_health_reporter_create - create devlink health reporter 5440 * 5441 * @devlink: devlink 5442 * @ops: ops 5443 * @graceful_period: to avoid recovery loops, in msecs 5444 * @priv: priv 5445 */ 5446struct devlink_health_reporter * 5447devlink_health_reporter_create(struct devlink *devlink, 5448 const struct devlink_health_reporter_ops *ops, 5449 u64 graceful_period, void *priv) 5450{ 5451 struct devlink_health_reporter *reporter; 5452 5453 mutex_lock(&devlink->reporters_lock); 5454 if (devlink_health_reporter_find_by_name(devlink, ops->name)) { 5455 reporter = ERR_PTR(-EEXIST); 5456 goto unlock; 5457 } 5458 5459 reporter = __devlink_health_reporter_create(devlink, ops, 5460 graceful_period, priv); 5461 if (IS_ERR(reporter)) 5462 goto unlock; 5463 5464 list_add_tail(&reporter->list, &devlink->reporter_list); 5465unlock: 5466 mutex_unlock(&devlink->reporters_lock); 5467 return reporter; 5468} 5469EXPORT_SYMBOL_GPL(devlink_health_reporter_create); 5470 5471static void 5472devlink_health_reporter_free(struct devlink_health_reporter *reporter) 5473{ 5474 mutex_destroy(&reporter->dump_lock); 5475 if (reporter->dump_fmsg) 5476 devlink_fmsg_free(reporter->dump_fmsg); 5477 kfree(reporter); 5478} 5479 5480static void 5481devlink_health_reporter_put(struct devlink_health_reporter *reporter) 5482{ 5483 if (refcount_dec_and_test(&reporter->refcount)) 5484 devlink_health_reporter_free(reporter); 5485} 5486 5487static void 5488__devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) 5489{ 5490 list_del(&reporter->list); 5491 devlink_health_reporter_put(reporter); 5492} 5493 5494/** 5495 * devlink_health_reporter_destroy - destroy devlink health reporter 5496 * 5497 * @reporter: devlink health reporter to destroy 5498 */ 5499void 5500devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) 5501{ 5502 struct mutex *lock = &reporter->devlink->reporters_lock; 5503 5504 mutex_lock(lock); 5505 __devlink_health_reporter_destroy(reporter); 5506 mutex_unlock(lock); 5507} 5508EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy); 5509 5510/** 5511 * devlink_port_health_reporter_destroy - destroy devlink port health reporter 5512 * 5513 * @reporter: devlink health reporter to destroy 5514 */ 5515void 5516devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter) 5517{ 5518 struct mutex *lock = &reporter->devlink_port->reporters_lock; 5519 5520 mutex_lock(lock); 5521 __devlink_health_reporter_destroy(reporter); 5522 mutex_unlock(lock); 5523} 5524EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy); 5525 5526static int 5527devlink_nl_health_reporter_fill(struct sk_buff *msg, 5528 struct devlink *devlink, 5529 struct devlink_health_reporter *reporter, 5530 enum devlink_command cmd, u32 portid, 5531 u32 seq, int flags) 5532{ 5533 struct nlattr *reporter_attr; 5534 void *hdr; 5535 5536 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 5537 if (!hdr) 5538 return -EMSGSIZE; 5539 5540 if (devlink_nl_put_handle(msg, devlink)) 5541 goto genlmsg_cancel; 5542 5543 if (reporter->devlink_port) { 5544 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, reporter->devlink_port->index)) 5545 goto genlmsg_cancel; 5546 } 5547 reporter_attr = nla_nest_start_noflag(msg, 5548 DEVLINK_ATTR_HEALTH_REPORTER); 5549 if (!reporter_attr) 5550 goto genlmsg_cancel; 5551 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME, 5552 reporter->ops->name)) 5553 goto reporter_nest_cancel; 5554 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE, 5555 reporter->health_state)) 5556 goto reporter_nest_cancel; 5557 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT, 5558 reporter->error_count, DEVLINK_ATTR_PAD)) 5559 goto reporter_nest_cancel; 5560 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT, 5561 reporter->recovery_count, DEVLINK_ATTR_PAD)) 5562 goto reporter_nest_cancel; 5563 if (reporter->ops->recover && 5564 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, 5565 reporter->graceful_period, 5566 DEVLINK_ATTR_PAD)) 5567 goto reporter_nest_cancel; 5568 if (reporter->ops->recover && 5569 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, 5570 reporter->auto_recover)) 5571 goto reporter_nest_cancel; 5572 if (reporter->dump_fmsg && 5573 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, 5574 jiffies_to_msecs(reporter->dump_ts), 5575 DEVLINK_ATTR_PAD)) 5576 goto reporter_nest_cancel; 5577 if (reporter->dump_fmsg && 5578 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS, 5579 reporter->dump_real_ts, DEVLINK_ATTR_PAD)) 5580 goto reporter_nest_cancel; 5581 if (reporter->ops->dump && 5582 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP, 5583 reporter->auto_dump)) 5584 goto reporter_nest_cancel; 5585 5586 nla_nest_end(msg, reporter_attr); 5587 genlmsg_end(msg, hdr); 5588 return 0; 5589 5590reporter_nest_cancel: 5591 nla_nest_end(msg, reporter_attr); 5592genlmsg_cancel: 5593 genlmsg_cancel(msg, hdr); 5594 return -EMSGSIZE; 5595} 5596 5597static void devlink_recover_notify(struct devlink_health_reporter *reporter, 5598 enum devlink_command cmd) 5599{ 5600 struct sk_buff *msg; 5601 int err; 5602 5603 WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER); 5604 5605 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 5606 if (!msg) 5607 return; 5608 5609 err = devlink_nl_health_reporter_fill(msg, reporter->devlink, 5610 reporter, cmd, 0, 0, 0); 5611 if (err) { 5612 nlmsg_free(msg); 5613 return; 5614 } 5615 5616 genlmsg_multicast_netns(&devlink_nl_family, 5617 devlink_net(reporter->devlink), 5618 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 5619} 5620 5621void 5622devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter) 5623{ 5624 reporter->recovery_count++; 5625 reporter->last_recovery_ts = jiffies; 5626} 5627EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done); 5628 5629static int 5630devlink_health_reporter_recover(struct devlink_health_reporter *reporter, 5631 void *priv_ctx, struct netlink_ext_ack *extack) 5632{ 5633 int err; 5634 5635 if (reporter->health_state == DEVLINK_HEALTH_REPORTER_STATE_HEALTHY) 5636 return 0; 5637 5638 if (!reporter->ops->recover) 5639 return -EOPNOTSUPP; 5640 5641 err = reporter->ops->recover(reporter, priv_ctx, extack); 5642 if (err) 5643 return err; 5644 5645 devlink_health_reporter_recovery_done(reporter); 5646 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY; 5647 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER); 5648 5649 return 0; 5650} 5651 5652static void 5653devlink_health_dump_clear(struct devlink_health_reporter *reporter) 5654{ 5655 if (!reporter->dump_fmsg) 5656 return; 5657 devlink_fmsg_free(reporter->dump_fmsg); 5658 reporter->dump_fmsg = NULL; 5659} 5660 5661static int devlink_health_do_dump(struct devlink_health_reporter *reporter, 5662 void *priv_ctx, 5663 struct netlink_ext_ack *extack) 5664{ 5665 int err; 5666 5667 if (!reporter->ops->dump) 5668 return 0; 5669 5670 if (reporter->dump_fmsg) 5671 return 0; 5672 5673 reporter->dump_fmsg = devlink_fmsg_alloc(); 5674 if (!reporter->dump_fmsg) { 5675 err = -ENOMEM; 5676 return err; 5677 } 5678 5679 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg); 5680 if (err) 5681 goto dump_err; 5682 5683 err = reporter->ops->dump(reporter, reporter->dump_fmsg, 5684 priv_ctx, extack); 5685 if (err) 5686 goto dump_err; 5687 5688 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg); 5689 if (err) 5690 goto dump_err; 5691 5692 reporter->dump_ts = jiffies; 5693 reporter->dump_real_ts = ktime_get_real_ns(); 5694 5695 return 0; 5696 5697dump_err: 5698 devlink_health_dump_clear(reporter); 5699 return err; 5700} 5701 5702int devlink_health_report(struct devlink_health_reporter *reporter, 5703 const char *msg, void *priv_ctx) 5704{ 5705 enum devlink_health_reporter_state prev_health_state; 5706 struct devlink *devlink = reporter->devlink; 5707 unsigned long recover_ts_threshold; 5708 5709 /* write a log message of the current error */ 5710 WARN_ON(!msg); 5711 trace_devlink_health_report(devlink, reporter->ops->name, msg); 5712 reporter->error_count++; 5713 prev_health_state = reporter->health_state; 5714 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 5715 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER); 5716 5717 /* abort if the previous error wasn't recovered */ 5718 recover_ts_threshold = reporter->last_recovery_ts + 5719 msecs_to_jiffies(reporter->graceful_period); 5720 if (reporter->auto_recover && 5721 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY || 5722 (reporter->last_recovery_ts && reporter->recovery_count && 5723 time_is_after_jiffies(recover_ts_threshold)))) { 5724 trace_devlink_health_recover_aborted(devlink, 5725 reporter->ops->name, 5726 reporter->health_state, 5727 jiffies - 5728 reporter->last_recovery_ts); 5729 return -ECANCELED; 5730 } 5731 5732 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 5733 5734 if (reporter->auto_dump) { 5735 mutex_lock(&reporter->dump_lock); 5736 /* store current dump of current error, for later analysis */ 5737 devlink_health_do_dump(reporter, priv_ctx, NULL); 5738 mutex_unlock(&reporter->dump_lock); 5739 } 5740 5741 if (reporter->auto_recover) 5742 return devlink_health_reporter_recover(reporter, 5743 priv_ctx, NULL); 5744 5745 return 0; 5746} 5747EXPORT_SYMBOL_GPL(devlink_health_report); 5748 5749static struct devlink_health_reporter * 5750devlink_health_reporter_get_from_attrs(struct devlink *devlink, 5751 struct nlattr **attrs) 5752{ 5753 struct devlink_health_reporter *reporter; 5754 struct devlink_port *devlink_port; 5755 char *reporter_name; 5756 5757 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]) 5758 return NULL; 5759 5760 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]); 5761 devlink_port = devlink_port_get_from_attrs(devlink, attrs); 5762 if (IS_ERR(devlink_port)) { 5763 mutex_lock(&devlink->reporters_lock); 5764 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name); 5765 if (reporter) 5766 refcount_inc(&reporter->refcount); 5767 mutex_unlock(&devlink->reporters_lock); 5768 } else { 5769 mutex_lock(&devlink_port->reporters_lock); 5770 reporter = devlink_port_health_reporter_find_by_name(devlink_port, reporter_name); 5771 if (reporter) 5772 refcount_inc(&reporter->refcount); 5773 mutex_unlock(&devlink_port->reporters_lock); 5774 } 5775 5776 return reporter; 5777} 5778 5779static struct devlink_health_reporter * 5780devlink_health_reporter_get_from_info(struct devlink *devlink, 5781 struct genl_info *info) 5782{ 5783 return devlink_health_reporter_get_from_attrs(devlink, info->attrs); 5784} 5785 5786static struct devlink_health_reporter * 5787devlink_health_reporter_get_from_cb(struct netlink_callback *cb) 5788{ 5789 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 5790 struct devlink_health_reporter *reporter; 5791 struct nlattr **attrs = info->attrs; 5792 struct devlink *devlink; 5793 5794 mutex_lock(&devlink_mutex); 5795 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 5796 if (IS_ERR(devlink)) 5797 goto unlock; 5798 5799 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs); 5800 mutex_unlock(&devlink_mutex); 5801 return reporter; 5802unlock: 5803 mutex_unlock(&devlink_mutex); 5804 return NULL; 5805} 5806 5807void 5808devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, 5809 enum devlink_health_reporter_state state) 5810{ 5811 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY && 5812 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR)) 5813 return; 5814 5815 if (reporter->health_state == state) 5816 return; 5817 5818 reporter->health_state = state; 5819 trace_devlink_health_reporter_state_update(reporter->devlink, 5820 reporter->ops->name, state); 5821 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER); 5822} 5823EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update); 5824 5825static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, 5826 struct genl_info *info) 5827{ 5828 struct devlink *devlink = info->user_ptr[0]; 5829 struct devlink_health_reporter *reporter; 5830 struct sk_buff *msg; 5831 int err; 5832 5833 reporter = devlink_health_reporter_get_from_info(devlink, info); 5834 if (!reporter) 5835 return -EINVAL; 5836 5837 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 5838 if (!msg) { 5839 err = -ENOMEM; 5840 goto out; 5841 } 5842 5843 err = devlink_nl_health_reporter_fill(msg, devlink, reporter, 5844 DEVLINK_CMD_HEALTH_REPORTER_GET, 5845 info->snd_portid, info->snd_seq, 5846 0); 5847 if (err) { 5848 nlmsg_free(msg); 5849 goto out; 5850 } 5851 5852 err = genlmsg_reply(msg, info); 5853out: 5854 devlink_health_reporter_put(reporter); 5855 return err; 5856} 5857 5858static int 5859devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, 5860 struct netlink_callback *cb) 5861{ 5862 struct devlink_health_reporter *reporter; 5863 struct devlink_port *port; 5864 struct devlink *devlink; 5865 int start = cb->args[0]; 5866 int idx = 0; 5867 int err; 5868 5869 mutex_lock(&devlink_mutex); 5870 list_for_each_entry(devlink, &devlink_list, list) { 5871 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 5872 continue; 5873 mutex_lock(&devlink->reporters_lock); 5874 list_for_each_entry(reporter, &devlink->reporter_list, 5875 list) { 5876 if (idx < start) { 5877 idx++; 5878 continue; 5879 } 5880 err = devlink_nl_health_reporter_fill(msg, devlink, 5881 reporter, 5882 DEVLINK_CMD_HEALTH_REPORTER_GET, 5883 NETLINK_CB(cb->skb).portid, 5884 cb->nlh->nlmsg_seq, 5885 NLM_F_MULTI); 5886 if (err) { 5887 mutex_unlock(&devlink->reporters_lock); 5888 goto out; 5889 } 5890 idx++; 5891 } 5892 mutex_unlock(&devlink->reporters_lock); 5893 } 5894 5895 list_for_each_entry(devlink, &devlink_list, list) { 5896 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 5897 continue; 5898 list_for_each_entry(port, &devlink->port_list, list) { 5899 mutex_lock(&port->reporters_lock); 5900 list_for_each_entry(reporter, &port->reporter_list, list) { 5901 if (idx < start) { 5902 idx++; 5903 continue; 5904 } 5905 err = devlink_nl_health_reporter_fill(msg, devlink, reporter, 5906 DEVLINK_CMD_HEALTH_REPORTER_GET, 5907 NETLINK_CB(cb->skb).portid, 5908 cb->nlh->nlmsg_seq, 5909 NLM_F_MULTI); 5910 if (err) { 5911 mutex_unlock(&port->reporters_lock); 5912 goto out; 5913 } 5914 idx++; 5915 } 5916 mutex_unlock(&port->reporters_lock); 5917 } 5918 } 5919out: 5920 mutex_unlock(&devlink_mutex); 5921 5922 cb->args[0] = idx; 5923 return msg->len; 5924} 5925 5926static int 5927devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, 5928 struct genl_info *info) 5929{ 5930 struct devlink *devlink = info->user_ptr[0]; 5931 struct devlink_health_reporter *reporter; 5932 int err; 5933 5934 reporter = devlink_health_reporter_get_from_info(devlink, info); 5935 if (!reporter) 5936 return -EINVAL; 5937 5938 if (!reporter->ops->recover && 5939 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] || 5940 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) { 5941 err = -EOPNOTSUPP; 5942 goto out; 5943 } 5944 if (!reporter->ops->dump && 5945 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) { 5946 err = -EOPNOTSUPP; 5947 goto out; 5948 } 5949 5950 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]) 5951 reporter->graceful_period = 5952 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]); 5953 5954 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]) 5955 reporter->auto_recover = 5956 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]); 5957 5958 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) 5959 reporter->auto_dump = 5960 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]); 5961 5962 devlink_health_reporter_put(reporter); 5963 return 0; 5964out: 5965 devlink_health_reporter_put(reporter); 5966 return err; 5967} 5968 5969static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, 5970 struct genl_info *info) 5971{ 5972 struct devlink *devlink = info->user_ptr[0]; 5973 struct devlink_health_reporter *reporter; 5974 int err; 5975 5976 reporter = devlink_health_reporter_get_from_info(devlink, info); 5977 if (!reporter) 5978 return -EINVAL; 5979 5980 err = devlink_health_reporter_recover(reporter, NULL, info->extack); 5981 5982 devlink_health_reporter_put(reporter); 5983 return err; 5984} 5985 5986static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, 5987 struct genl_info *info) 5988{ 5989 struct devlink *devlink = info->user_ptr[0]; 5990 struct devlink_health_reporter *reporter; 5991 struct devlink_fmsg *fmsg; 5992 int err; 5993 5994 reporter = devlink_health_reporter_get_from_info(devlink, info); 5995 if (!reporter) 5996 return -EINVAL; 5997 5998 if (!reporter->ops->diagnose) { 5999 devlink_health_reporter_put(reporter); 6000 return -EOPNOTSUPP; 6001 } 6002 6003 fmsg = devlink_fmsg_alloc(); 6004 if (!fmsg) { 6005 devlink_health_reporter_put(reporter); 6006 return -ENOMEM; 6007 } 6008 6009 err = devlink_fmsg_obj_nest_start(fmsg); 6010 if (err) 6011 goto out; 6012 6013 err = reporter->ops->diagnose(reporter, fmsg, info->extack); 6014 if (err) 6015 goto out; 6016 6017 err = devlink_fmsg_obj_nest_end(fmsg); 6018 if (err) 6019 goto out; 6020 6021 err = devlink_fmsg_snd(fmsg, info, 6022 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0); 6023 6024out: 6025 devlink_fmsg_free(fmsg); 6026 devlink_health_reporter_put(reporter); 6027 return err; 6028} 6029 6030static int 6031devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, 6032 struct netlink_callback *cb) 6033{ 6034 struct devlink_health_reporter *reporter; 6035 u64 start = cb->args[0]; 6036 int err; 6037 6038 reporter = devlink_health_reporter_get_from_cb(cb); 6039 if (!reporter) 6040 return -EINVAL; 6041 6042 if (!reporter->ops->dump) { 6043 err = -EOPNOTSUPP; 6044 goto out; 6045 } 6046 mutex_lock(&reporter->dump_lock); 6047 if (!start) { 6048 err = devlink_health_do_dump(reporter, NULL, cb->extack); 6049 if (err) 6050 goto unlock; 6051 cb->args[1] = reporter->dump_ts; 6052 } 6053 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) { 6054 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry"); 6055 err = -EAGAIN; 6056 goto unlock; 6057 } 6058 6059 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb, 6060 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET); 6061unlock: 6062 mutex_unlock(&reporter->dump_lock); 6063out: 6064 devlink_health_reporter_put(reporter); 6065 return err; 6066} 6067 6068static int 6069devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, 6070 struct genl_info *info) 6071{ 6072 struct devlink *devlink = info->user_ptr[0]; 6073 struct devlink_health_reporter *reporter; 6074 6075 reporter = devlink_health_reporter_get_from_info(devlink, info); 6076 if (!reporter) 6077 return -EINVAL; 6078 6079 if (!reporter->ops->dump) { 6080 devlink_health_reporter_put(reporter); 6081 return -EOPNOTSUPP; 6082 } 6083 6084 mutex_lock(&reporter->dump_lock); 6085 devlink_health_dump_clear(reporter); 6086 mutex_unlock(&reporter->dump_lock); 6087 devlink_health_reporter_put(reporter); 6088 return 0; 6089} 6090 6091struct devlink_stats { 6092 u64 rx_bytes; 6093 u64 rx_packets; 6094 struct u64_stats_sync syncp; 6095}; 6096 6097/** 6098 * struct devlink_trap_policer_item - Packet trap policer attributes. 6099 * @policer: Immutable packet trap policer attributes. 6100 * @rate: Rate in packets / sec. 6101 * @burst: Burst size in packets. 6102 * @list: trap_policer_list member. 6103 * 6104 * Describes packet trap policer attributes. Created by devlink during trap 6105 * policer registration. 6106 */ 6107struct devlink_trap_policer_item { 6108 const struct devlink_trap_policer *policer; 6109 u64 rate; 6110 u64 burst; 6111 struct list_head list; 6112}; 6113 6114/** 6115 * struct devlink_trap_group_item - Packet trap group attributes. 6116 * @group: Immutable packet trap group attributes. 6117 * @policer_item: Associated policer item. Can be NULL. 6118 * @list: trap_group_list member. 6119 * @stats: Trap group statistics. 6120 * 6121 * Describes packet trap group attributes. Created by devlink during trap 6122 * group registration. 6123 */ 6124struct devlink_trap_group_item { 6125 const struct devlink_trap_group *group; 6126 struct devlink_trap_policer_item *policer_item; 6127 struct list_head list; 6128 struct devlink_stats __percpu *stats; 6129}; 6130 6131/** 6132 * struct devlink_trap_item - Packet trap attributes. 6133 * @trap: Immutable packet trap attributes. 6134 * @group_item: Associated group item. 6135 * @list: trap_list member. 6136 * @action: Trap action. 6137 * @stats: Trap statistics. 6138 * @priv: Driver private information. 6139 * 6140 * Describes both mutable and immutable packet trap attributes. Created by 6141 * devlink during trap registration and used for all trap related operations. 6142 */ 6143struct devlink_trap_item { 6144 const struct devlink_trap *trap; 6145 struct devlink_trap_group_item *group_item; 6146 struct list_head list; 6147 enum devlink_trap_action action; 6148 struct devlink_stats __percpu *stats; 6149 void *priv; 6150}; 6151 6152static struct devlink_trap_policer_item * 6153devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id) 6154{ 6155 struct devlink_trap_policer_item *policer_item; 6156 6157 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 6158 if (policer_item->policer->id == id) 6159 return policer_item; 6160 } 6161 6162 return NULL; 6163} 6164 6165static struct devlink_trap_item * 6166devlink_trap_item_lookup(struct devlink *devlink, const char *name) 6167{ 6168 struct devlink_trap_item *trap_item; 6169 6170 list_for_each_entry(trap_item, &devlink->trap_list, list) { 6171 if (!strcmp(trap_item->trap->name, name)) 6172 return trap_item; 6173 } 6174 6175 return NULL; 6176} 6177 6178static struct devlink_trap_item * 6179devlink_trap_item_get_from_info(struct devlink *devlink, 6180 struct genl_info *info) 6181{ 6182 struct nlattr *attr; 6183 6184 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME]) 6185 return NULL; 6186 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME]; 6187 6188 return devlink_trap_item_lookup(devlink, nla_data(attr)); 6189} 6190 6191static int 6192devlink_trap_action_get_from_info(struct genl_info *info, 6193 enum devlink_trap_action *p_trap_action) 6194{ 6195 u8 val; 6196 6197 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]); 6198 switch (val) { 6199 case DEVLINK_TRAP_ACTION_DROP: 6200 case DEVLINK_TRAP_ACTION_TRAP: 6201 case DEVLINK_TRAP_ACTION_MIRROR: 6202 *p_trap_action = val; 6203 break; 6204 default: 6205 return -EINVAL; 6206 } 6207 6208 return 0; 6209} 6210 6211static int devlink_trap_metadata_put(struct sk_buff *msg, 6212 const struct devlink_trap *trap) 6213{ 6214 struct nlattr *attr; 6215 6216 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA); 6217 if (!attr) 6218 return -EMSGSIZE; 6219 6220 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) && 6221 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT)) 6222 goto nla_put_failure; 6223 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) && 6224 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE)) 6225 goto nla_put_failure; 6226 6227 nla_nest_end(msg, attr); 6228 6229 return 0; 6230 6231nla_put_failure: 6232 nla_nest_cancel(msg, attr); 6233 return -EMSGSIZE; 6234} 6235 6236static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats, 6237 struct devlink_stats *stats) 6238{ 6239 int i; 6240 6241 memset(stats, 0, sizeof(*stats)); 6242 for_each_possible_cpu(i) { 6243 struct devlink_stats *cpu_stats; 6244 u64 rx_packets, rx_bytes; 6245 unsigned int start; 6246 6247 cpu_stats = per_cpu_ptr(trap_stats, i); 6248 do { 6249 start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 6250 rx_packets = cpu_stats->rx_packets; 6251 rx_bytes = cpu_stats->rx_bytes; 6252 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); 6253 6254 stats->rx_packets += rx_packets; 6255 stats->rx_bytes += rx_bytes; 6256 } 6257} 6258 6259static int devlink_trap_stats_put(struct sk_buff *msg, 6260 struct devlink_stats __percpu *trap_stats) 6261{ 6262 struct devlink_stats stats; 6263 struct nlattr *attr; 6264 6265 devlink_trap_stats_read(trap_stats, &stats); 6266 6267 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 6268 if (!attr) 6269 return -EMSGSIZE; 6270 6271 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 6272 stats.rx_packets, DEVLINK_ATTR_PAD)) 6273 goto nla_put_failure; 6274 6275 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES, 6276 stats.rx_bytes, DEVLINK_ATTR_PAD)) 6277 goto nla_put_failure; 6278 6279 nla_nest_end(msg, attr); 6280 6281 return 0; 6282 6283nla_put_failure: 6284 nla_nest_cancel(msg, attr); 6285 return -EMSGSIZE; 6286} 6287 6288static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink, 6289 const struct devlink_trap_item *trap_item, 6290 enum devlink_command cmd, u32 portid, u32 seq, 6291 int flags) 6292{ 6293 struct devlink_trap_group_item *group_item = trap_item->group_item; 6294 void *hdr; 6295 int err; 6296 6297 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 6298 if (!hdr) 6299 return -EMSGSIZE; 6300 6301 if (devlink_nl_put_handle(msg, devlink)) 6302 goto nla_put_failure; 6303 6304 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 6305 group_item->group->name)) 6306 goto nla_put_failure; 6307 6308 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name)) 6309 goto nla_put_failure; 6310 6311 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type)) 6312 goto nla_put_failure; 6313 6314 if (trap_item->trap->generic && 6315 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 6316 goto nla_put_failure; 6317 6318 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action)) 6319 goto nla_put_failure; 6320 6321 err = devlink_trap_metadata_put(msg, trap_item->trap); 6322 if (err) 6323 goto nla_put_failure; 6324 6325 err = devlink_trap_stats_put(msg, trap_item->stats); 6326 if (err) 6327 goto nla_put_failure; 6328 6329 genlmsg_end(msg, hdr); 6330 6331 return 0; 6332 6333nla_put_failure: 6334 genlmsg_cancel(msg, hdr); 6335 return -EMSGSIZE; 6336} 6337 6338static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb, 6339 struct genl_info *info) 6340{ 6341 struct netlink_ext_ack *extack = info->extack; 6342 struct devlink *devlink = info->user_ptr[0]; 6343 struct devlink_trap_item *trap_item; 6344 struct sk_buff *msg; 6345 int err; 6346 6347 if (list_empty(&devlink->trap_list)) 6348 return -EOPNOTSUPP; 6349 6350 trap_item = devlink_trap_item_get_from_info(devlink, info); 6351 if (!trap_item) { 6352 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap"); 6353 return -ENOENT; 6354 } 6355 6356 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 6357 if (!msg) 6358 return -ENOMEM; 6359 6360 err = devlink_nl_trap_fill(msg, devlink, trap_item, 6361 DEVLINK_CMD_TRAP_NEW, info->snd_portid, 6362 info->snd_seq, 0); 6363 if (err) 6364 goto err_trap_fill; 6365 6366 return genlmsg_reply(msg, info); 6367 6368err_trap_fill: 6369 nlmsg_free(msg); 6370 return err; 6371} 6372 6373static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg, 6374 struct netlink_callback *cb) 6375{ 6376 struct devlink_trap_item *trap_item; 6377 struct devlink *devlink; 6378 int start = cb->args[0]; 6379 int idx = 0; 6380 int err; 6381 6382 mutex_lock(&devlink_mutex); 6383 list_for_each_entry(devlink, &devlink_list, list) { 6384 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 6385 continue; 6386 mutex_lock(&devlink->lock); 6387 list_for_each_entry(trap_item, &devlink->trap_list, list) { 6388 if (idx < start) { 6389 idx++; 6390 continue; 6391 } 6392 err = devlink_nl_trap_fill(msg, devlink, trap_item, 6393 DEVLINK_CMD_TRAP_NEW, 6394 NETLINK_CB(cb->skb).portid, 6395 cb->nlh->nlmsg_seq, 6396 NLM_F_MULTI); 6397 if (err) { 6398 mutex_unlock(&devlink->lock); 6399 goto out; 6400 } 6401 idx++; 6402 } 6403 mutex_unlock(&devlink->lock); 6404 } 6405out: 6406 mutex_unlock(&devlink_mutex); 6407 6408 cb->args[0] = idx; 6409 return msg->len; 6410} 6411 6412static int __devlink_trap_action_set(struct devlink *devlink, 6413 struct devlink_trap_item *trap_item, 6414 enum devlink_trap_action trap_action, 6415 struct netlink_ext_ack *extack) 6416{ 6417 int err; 6418 6419 if (trap_item->action != trap_action && 6420 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) { 6421 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping"); 6422 return 0; 6423 } 6424 6425 err = devlink->ops->trap_action_set(devlink, trap_item->trap, 6426 trap_action, extack); 6427 if (err) 6428 return err; 6429 6430 trap_item->action = trap_action; 6431 6432 return 0; 6433} 6434 6435static int devlink_trap_action_set(struct devlink *devlink, 6436 struct devlink_trap_item *trap_item, 6437 struct genl_info *info) 6438{ 6439 enum devlink_trap_action trap_action; 6440 int err; 6441 6442 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 6443 return 0; 6444 6445 err = devlink_trap_action_get_from_info(info, &trap_action); 6446 if (err) { 6447 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action"); 6448 return -EINVAL; 6449 } 6450 6451 return __devlink_trap_action_set(devlink, trap_item, trap_action, 6452 info->extack); 6453} 6454 6455static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb, 6456 struct genl_info *info) 6457{ 6458 struct netlink_ext_ack *extack = info->extack; 6459 struct devlink *devlink = info->user_ptr[0]; 6460 struct devlink_trap_item *trap_item; 6461 int err; 6462 6463 if (list_empty(&devlink->trap_list)) 6464 return -EOPNOTSUPP; 6465 6466 trap_item = devlink_trap_item_get_from_info(devlink, info); 6467 if (!trap_item) { 6468 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap"); 6469 return -ENOENT; 6470 } 6471 6472 err = devlink_trap_action_set(devlink, trap_item, info); 6473 if (err) 6474 return err; 6475 6476 return 0; 6477} 6478 6479static struct devlink_trap_group_item * 6480devlink_trap_group_item_lookup(struct devlink *devlink, const char *name) 6481{ 6482 struct devlink_trap_group_item *group_item; 6483 6484 list_for_each_entry(group_item, &devlink->trap_group_list, list) { 6485 if (!strcmp(group_item->group->name, name)) 6486 return group_item; 6487 } 6488 6489 return NULL; 6490} 6491 6492static struct devlink_trap_group_item * 6493devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id) 6494{ 6495 struct devlink_trap_group_item *group_item; 6496 6497 list_for_each_entry(group_item, &devlink->trap_group_list, list) { 6498 if (group_item->group->id == id) 6499 return group_item; 6500 } 6501 6502 return NULL; 6503} 6504 6505static struct devlink_trap_group_item * 6506devlink_trap_group_item_get_from_info(struct devlink *devlink, 6507 struct genl_info *info) 6508{ 6509 char *name; 6510 6511 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]) 6512 return NULL; 6513 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]); 6514 6515 return devlink_trap_group_item_lookup(devlink, name); 6516} 6517 6518static int 6519devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink, 6520 const struct devlink_trap_group_item *group_item, 6521 enum devlink_command cmd, u32 portid, u32 seq, 6522 int flags) 6523{ 6524 void *hdr; 6525 int err; 6526 6527 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 6528 if (!hdr) 6529 return -EMSGSIZE; 6530 6531 if (devlink_nl_put_handle(msg, devlink)) 6532 goto nla_put_failure; 6533 6534 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 6535 group_item->group->name)) 6536 goto nla_put_failure; 6537 6538 if (group_item->group->generic && 6539 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 6540 goto nla_put_failure; 6541 6542 if (group_item->policer_item && 6543 nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 6544 group_item->policer_item->policer->id)) 6545 goto nla_put_failure; 6546 6547 err = devlink_trap_stats_put(msg, group_item->stats); 6548 if (err) 6549 goto nla_put_failure; 6550 6551 genlmsg_end(msg, hdr); 6552 6553 return 0; 6554 6555nla_put_failure: 6556 genlmsg_cancel(msg, hdr); 6557 return -EMSGSIZE; 6558} 6559 6560static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb, 6561 struct genl_info *info) 6562{ 6563 struct netlink_ext_ack *extack = info->extack; 6564 struct devlink *devlink = info->user_ptr[0]; 6565 struct devlink_trap_group_item *group_item; 6566 struct sk_buff *msg; 6567 int err; 6568 6569 if (list_empty(&devlink->trap_group_list)) 6570 return -EOPNOTSUPP; 6571 6572 group_item = devlink_trap_group_item_get_from_info(devlink, info); 6573 if (!group_item) { 6574 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group"); 6575 return -ENOENT; 6576 } 6577 6578 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 6579 if (!msg) 6580 return -ENOMEM; 6581 6582 err = devlink_nl_trap_group_fill(msg, devlink, group_item, 6583 DEVLINK_CMD_TRAP_GROUP_NEW, 6584 info->snd_portid, info->snd_seq, 0); 6585 if (err) 6586 goto err_trap_group_fill; 6587 6588 return genlmsg_reply(msg, info); 6589 6590err_trap_group_fill: 6591 nlmsg_free(msg); 6592 return err; 6593} 6594 6595static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg, 6596 struct netlink_callback *cb) 6597{ 6598 enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW; 6599 struct devlink_trap_group_item *group_item; 6600 u32 portid = NETLINK_CB(cb->skb).portid; 6601 struct devlink *devlink; 6602 int start = cb->args[0]; 6603 int idx = 0; 6604 int err; 6605 6606 mutex_lock(&devlink_mutex); 6607 list_for_each_entry(devlink, &devlink_list, list) { 6608 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 6609 continue; 6610 mutex_lock(&devlink->lock); 6611 list_for_each_entry(group_item, &devlink->trap_group_list, 6612 list) { 6613 if (idx < start) { 6614 idx++; 6615 continue; 6616 } 6617 err = devlink_nl_trap_group_fill(msg, devlink, 6618 group_item, cmd, 6619 portid, 6620 cb->nlh->nlmsg_seq, 6621 NLM_F_MULTI); 6622 if (err) { 6623 mutex_unlock(&devlink->lock); 6624 goto out; 6625 } 6626 idx++; 6627 } 6628 mutex_unlock(&devlink->lock); 6629 } 6630out: 6631 mutex_unlock(&devlink_mutex); 6632 6633 cb->args[0] = idx; 6634 return msg->len; 6635} 6636 6637static int 6638__devlink_trap_group_action_set(struct devlink *devlink, 6639 struct devlink_trap_group_item *group_item, 6640 enum devlink_trap_action trap_action, 6641 struct netlink_ext_ack *extack) 6642{ 6643 const char *group_name = group_item->group->name; 6644 struct devlink_trap_item *trap_item; 6645 int err; 6646 6647 list_for_each_entry(trap_item, &devlink->trap_list, list) { 6648 if (strcmp(trap_item->group_item->group->name, group_name)) 6649 continue; 6650 err = __devlink_trap_action_set(devlink, trap_item, 6651 trap_action, extack); 6652 if (err) 6653 return err; 6654 } 6655 6656 return 0; 6657} 6658 6659static int 6660devlink_trap_group_action_set(struct devlink *devlink, 6661 struct devlink_trap_group_item *group_item, 6662 struct genl_info *info, bool *p_modified) 6663{ 6664 enum devlink_trap_action trap_action; 6665 int err; 6666 6667 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 6668 return 0; 6669 6670 err = devlink_trap_action_get_from_info(info, &trap_action); 6671 if (err) { 6672 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action"); 6673 return -EINVAL; 6674 } 6675 6676 err = __devlink_trap_group_action_set(devlink, group_item, trap_action, 6677 info->extack); 6678 if (err) 6679 return err; 6680 6681 *p_modified = true; 6682 6683 return 0; 6684} 6685 6686static int devlink_trap_group_set(struct devlink *devlink, 6687 struct devlink_trap_group_item *group_item, 6688 struct genl_info *info) 6689{ 6690 struct devlink_trap_policer_item *policer_item; 6691 struct netlink_ext_ack *extack = info->extack; 6692 const struct devlink_trap_policer *policer; 6693 struct nlattr **attrs = info->attrs; 6694 int err; 6695 6696 if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 6697 return 0; 6698 6699 if (!devlink->ops->trap_group_set) 6700 return -EOPNOTSUPP; 6701 6702 policer_item = group_item->policer_item; 6703 if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) { 6704 u32 policer_id; 6705 6706 policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 6707 policer_item = devlink_trap_policer_item_lookup(devlink, 6708 policer_id); 6709 if (policer_id && !policer_item) { 6710 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer"); 6711 return -ENOENT; 6712 } 6713 } 6714 policer = policer_item ? policer_item->policer : NULL; 6715 6716 err = devlink->ops->trap_group_set(devlink, group_item->group, policer, 6717 extack); 6718 if (err) 6719 return err; 6720 6721 group_item->policer_item = policer_item; 6722 6723 return 0; 6724} 6725 6726static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb, 6727 struct genl_info *info) 6728{ 6729 struct netlink_ext_ack *extack = info->extack; 6730 struct devlink *devlink = info->user_ptr[0]; 6731 struct devlink_trap_group_item *group_item; 6732 bool modified = false; 6733 int err; 6734 6735 if (list_empty(&devlink->trap_group_list)) 6736 return -EOPNOTSUPP; 6737 6738 group_item = devlink_trap_group_item_get_from_info(devlink, info); 6739 if (!group_item) { 6740 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group"); 6741 return -ENOENT; 6742 } 6743 6744 err = devlink_trap_group_action_set(devlink, group_item, info, 6745 &modified); 6746 if (err) 6747 return err; 6748 6749 err = devlink_trap_group_set(devlink, group_item, info); 6750 if (err) 6751 goto err_trap_group_set; 6752 6753 return 0; 6754 6755err_trap_group_set: 6756 if (modified) 6757 NL_SET_ERR_MSG_MOD(extack, "Trap group set failed, but some changes were committed already"); 6758 return err; 6759} 6760 6761static struct devlink_trap_policer_item * 6762devlink_trap_policer_item_get_from_info(struct devlink *devlink, 6763 struct genl_info *info) 6764{ 6765 u32 id; 6766 6767 if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 6768 return NULL; 6769 id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 6770 6771 return devlink_trap_policer_item_lookup(devlink, id); 6772} 6773 6774static int 6775devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink, 6776 const struct devlink_trap_policer *policer) 6777{ 6778 struct nlattr *attr; 6779 u64 drops; 6780 int err; 6781 6782 if (!devlink->ops->trap_policer_counter_get) 6783 return 0; 6784 6785 err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops); 6786 if (err) 6787 return err; 6788 6789 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 6790 if (!attr) 6791 return -EMSGSIZE; 6792 6793 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops, 6794 DEVLINK_ATTR_PAD)) 6795 goto nla_put_failure; 6796 6797 nla_nest_end(msg, attr); 6798 6799 return 0; 6800 6801nla_put_failure: 6802 nla_nest_cancel(msg, attr); 6803 return -EMSGSIZE; 6804} 6805 6806static int 6807devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink, 6808 const struct devlink_trap_policer_item *policer_item, 6809 enum devlink_command cmd, u32 portid, u32 seq, 6810 int flags) 6811{ 6812 void *hdr; 6813 int err; 6814 6815 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 6816 if (!hdr) 6817 return -EMSGSIZE; 6818 6819 if (devlink_nl_put_handle(msg, devlink)) 6820 goto nla_put_failure; 6821 6822 if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 6823 policer_item->policer->id)) 6824 goto nla_put_failure; 6825 6826 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE, 6827 policer_item->rate, DEVLINK_ATTR_PAD)) 6828 goto nla_put_failure; 6829 6830 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST, 6831 policer_item->burst, DEVLINK_ATTR_PAD)) 6832 goto nla_put_failure; 6833 6834 err = devlink_trap_policer_stats_put(msg, devlink, 6835 policer_item->policer); 6836 if (err) 6837 goto nla_put_failure; 6838 6839 genlmsg_end(msg, hdr); 6840 6841 return 0; 6842 6843nla_put_failure: 6844 genlmsg_cancel(msg, hdr); 6845 return -EMSGSIZE; 6846} 6847 6848static int devlink_nl_cmd_trap_policer_get_doit(struct sk_buff *skb, 6849 struct genl_info *info) 6850{ 6851 struct devlink_trap_policer_item *policer_item; 6852 struct netlink_ext_ack *extack = info->extack; 6853 struct devlink *devlink = info->user_ptr[0]; 6854 struct sk_buff *msg; 6855 int err; 6856 6857 if (list_empty(&devlink->trap_policer_list)) 6858 return -EOPNOTSUPP; 6859 6860 policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 6861 if (!policer_item) { 6862 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer"); 6863 return -ENOENT; 6864 } 6865 6866 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 6867 if (!msg) 6868 return -ENOMEM; 6869 6870 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 6871 DEVLINK_CMD_TRAP_POLICER_NEW, 6872 info->snd_portid, info->snd_seq, 0); 6873 if (err) 6874 goto err_trap_policer_fill; 6875 6876 return genlmsg_reply(msg, info); 6877 6878err_trap_policer_fill: 6879 nlmsg_free(msg); 6880 return err; 6881} 6882 6883static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg, 6884 struct netlink_callback *cb) 6885{ 6886 enum devlink_command cmd = DEVLINK_CMD_TRAP_POLICER_NEW; 6887 struct devlink_trap_policer_item *policer_item; 6888 u32 portid = NETLINK_CB(cb->skb).portid; 6889 struct devlink *devlink; 6890 int start = cb->args[0]; 6891 int idx = 0; 6892 int err; 6893 6894 mutex_lock(&devlink_mutex); 6895 list_for_each_entry(devlink, &devlink_list, list) { 6896 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 6897 continue; 6898 mutex_lock(&devlink->lock); 6899 list_for_each_entry(policer_item, &devlink->trap_policer_list, 6900 list) { 6901 if (idx < start) { 6902 idx++; 6903 continue; 6904 } 6905 err = devlink_nl_trap_policer_fill(msg, devlink, 6906 policer_item, cmd, 6907 portid, 6908 cb->nlh->nlmsg_seq, 6909 NLM_F_MULTI); 6910 if (err) { 6911 mutex_unlock(&devlink->lock); 6912 goto out; 6913 } 6914 idx++; 6915 } 6916 mutex_unlock(&devlink->lock); 6917 } 6918out: 6919 mutex_unlock(&devlink_mutex); 6920 6921 cb->args[0] = idx; 6922 return msg->len; 6923} 6924 6925static int 6926devlink_trap_policer_set(struct devlink *devlink, 6927 struct devlink_trap_policer_item *policer_item, 6928 struct genl_info *info) 6929{ 6930 struct netlink_ext_ack *extack = info->extack; 6931 struct nlattr **attrs = info->attrs; 6932 u64 rate, burst; 6933 int err; 6934 6935 rate = policer_item->rate; 6936 burst = policer_item->burst; 6937 6938 if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]) 6939 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]); 6940 6941 if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]) 6942 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]); 6943 6944 if (rate < policer_item->policer->min_rate) { 6945 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit"); 6946 return -EINVAL; 6947 } 6948 6949 if (rate > policer_item->policer->max_rate) { 6950 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit"); 6951 return -EINVAL; 6952 } 6953 6954 if (burst < policer_item->policer->min_burst) { 6955 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit"); 6956 return -EINVAL; 6957 } 6958 6959 if (burst > policer_item->policer->max_burst) { 6960 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit"); 6961 return -EINVAL; 6962 } 6963 6964 err = devlink->ops->trap_policer_set(devlink, policer_item->policer, 6965 rate, burst, info->extack); 6966 if (err) 6967 return err; 6968 6969 policer_item->rate = rate; 6970 policer_item->burst = burst; 6971 6972 return 0; 6973} 6974 6975static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb, 6976 struct genl_info *info) 6977{ 6978 struct devlink_trap_policer_item *policer_item; 6979 struct netlink_ext_ack *extack = info->extack; 6980 struct devlink *devlink = info->user_ptr[0]; 6981 6982 if (list_empty(&devlink->trap_policer_list)) 6983 return -EOPNOTSUPP; 6984 6985 if (!devlink->ops->trap_policer_set) 6986 return -EOPNOTSUPP; 6987 6988 policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 6989 if (!policer_item) { 6990 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer"); 6991 return -ENOENT; 6992 } 6993 6994 return devlink_trap_policer_set(devlink, policer_item, info); 6995} 6996 6997static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 6998 [DEVLINK_ATTR_UNSPEC] = { .strict_start_type = 6999 DEVLINK_ATTR_TRAP_POLICER_ID }, 7000 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 7001 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 7002 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 7003 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 7004 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 7005 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 7006 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 7007 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 7008 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 7009 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 7010 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 7011 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 7012 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 7013 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 7014 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 7015 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 7016 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 7017 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 7018 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 7019 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 7020 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 7021 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 7022 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 7023 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 7024 [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 }, 7025 [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 }, 7026 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING }, 7027 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 }, 7028 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 }, 7029 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING }, 7030 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING }, 7031 [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING }, 7032 [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 }, 7033 [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING }, 7034 [DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 }, 7035 [DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 }, 7036 [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 }, 7037 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP] = { .type = NLA_U8 }, 7038 [DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 }, 7039 [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 }, 7040 [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 }, 7041 [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED }, 7042}; 7043 7044static const struct genl_ops devlink_nl_ops[] = { 7045 { 7046 .cmd = DEVLINK_CMD_GET, 7047 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7048 .doit = devlink_nl_cmd_get_doit, 7049 .dumpit = devlink_nl_cmd_get_dumpit, 7050 /* can be retrieved by unprivileged users */ 7051 }, 7052 { 7053 .cmd = DEVLINK_CMD_PORT_GET, 7054 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7055 .doit = devlink_nl_cmd_port_get_doit, 7056 .dumpit = devlink_nl_cmd_port_get_dumpit, 7057 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7058 /* can be retrieved by unprivileged users */ 7059 }, 7060 { 7061 .cmd = DEVLINK_CMD_PORT_SET, 7062 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7063 .doit = devlink_nl_cmd_port_set_doit, 7064 .flags = GENL_ADMIN_PERM, 7065 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7066 }, 7067 { 7068 .cmd = DEVLINK_CMD_PORT_SPLIT, 7069 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7070 .doit = devlink_nl_cmd_port_split_doit, 7071 .flags = GENL_ADMIN_PERM, 7072 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, 7073 }, 7074 { 7075 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 7076 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7077 .doit = devlink_nl_cmd_port_unsplit_doit, 7078 .flags = GENL_ADMIN_PERM, 7079 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, 7080 }, 7081 { 7082 .cmd = DEVLINK_CMD_SB_GET, 7083 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7084 .doit = devlink_nl_cmd_sb_get_doit, 7085 .dumpit = devlink_nl_cmd_sb_get_dumpit, 7086 /* can be retrieved by unprivileged users */ 7087 }, 7088 { 7089 .cmd = DEVLINK_CMD_SB_POOL_GET, 7090 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7091 .doit = devlink_nl_cmd_sb_pool_get_doit, 7092 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 7093 /* can be retrieved by unprivileged users */ 7094 }, 7095 { 7096 .cmd = DEVLINK_CMD_SB_POOL_SET, 7097 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7098 .doit = devlink_nl_cmd_sb_pool_set_doit, 7099 .flags = GENL_ADMIN_PERM, 7100 }, 7101 { 7102 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 7103 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7104 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 7105 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 7106 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7107 /* can be retrieved by unprivileged users */ 7108 }, 7109 { 7110 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 7111 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7112 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 7113 .flags = GENL_ADMIN_PERM, 7114 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7115 }, 7116 { 7117 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 7118 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7119 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 7120 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 7121 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7122 /* can be retrieved by unprivileged users */ 7123 }, 7124 { 7125 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 7126 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7127 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 7128 .flags = GENL_ADMIN_PERM, 7129 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7130 }, 7131 { 7132 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 7133 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7134 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 7135 .flags = GENL_ADMIN_PERM, 7136 }, 7137 { 7138 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 7139 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7140 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 7141 .flags = GENL_ADMIN_PERM, 7142 }, 7143 { 7144 .cmd = DEVLINK_CMD_ESWITCH_GET, 7145 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7146 .doit = devlink_nl_cmd_eswitch_get_doit, 7147 .flags = GENL_ADMIN_PERM, 7148 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, 7149 }, 7150 { 7151 .cmd = DEVLINK_CMD_ESWITCH_SET, 7152 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7153 .doit = devlink_nl_cmd_eswitch_set_doit, 7154 .flags = GENL_ADMIN_PERM, 7155 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, 7156 }, 7157 { 7158 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 7159 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7160 .doit = devlink_nl_cmd_dpipe_table_get, 7161 /* can be retrieved by unprivileged users */ 7162 }, 7163 { 7164 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 7165 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7166 .doit = devlink_nl_cmd_dpipe_entries_get, 7167 /* can be retrieved by unprivileged users */ 7168 }, 7169 { 7170 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 7171 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7172 .doit = devlink_nl_cmd_dpipe_headers_get, 7173 /* can be retrieved by unprivileged users */ 7174 }, 7175 { 7176 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 7177 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7178 .doit = devlink_nl_cmd_dpipe_table_counters_set, 7179 .flags = GENL_ADMIN_PERM, 7180 }, 7181 { 7182 .cmd = DEVLINK_CMD_RESOURCE_SET, 7183 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7184 .doit = devlink_nl_cmd_resource_set, 7185 .flags = GENL_ADMIN_PERM, 7186 }, 7187 { 7188 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 7189 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7190 .doit = devlink_nl_cmd_resource_dump, 7191 /* can be retrieved by unprivileged users */ 7192 }, 7193 { 7194 .cmd = DEVLINK_CMD_RELOAD, 7195 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7196 .doit = devlink_nl_cmd_reload, 7197 .flags = GENL_ADMIN_PERM, 7198 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, 7199 }, 7200 { 7201 .cmd = DEVLINK_CMD_PARAM_GET, 7202 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7203 .doit = devlink_nl_cmd_param_get_doit, 7204 .dumpit = devlink_nl_cmd_param_get_dumpit, 7205 /* can be retrieved by unprivileged users */ 7206 }, 7207 { 7208 .cmd = DEVLINK_CMD_PARAM_SET, 7209 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7210 .doit = devlink_nl_cmd_param_set_doit, 7211 .flags = GENL_ADMIN_PERM, 7212 }, 7213 { 7214 .cmd = DEVLINK_CMD_PORT_PARAM_GET, 7215 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7216 .doit = devlink_nl_cmd_port_param_get_doit, 7217 .dumpit = devlink_nl_cmd_port_param_get_dumpit, 7218 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7219 /* can be retrieved by unprivileged users */ 7220 }, 7221 { 7222 .cmd = DEVLINK_CMD_PORT_PARAM_SET, 7223 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7224 .doit = devlink_nl_cmd_port_param_set_doit, 7225 .flags = GENL_ADMIN_PERM, 7226 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 7227 }, 7228 { 7229 .cmd = DEVLINK_CMD_REGION_GET, 7230 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7231 .doit = devlink_nl_cmd_region_get_doit, 7232 .dumpit = devlink_nl_cmd_region_get_dumpit, 7233 .flags = GENL_ADMIN_PERM, 7234 }, 7235 { 7236 .cmd = DEVLINK_CMD_REGION_NEW, 7237 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7238 .doit = devlink_nl_cmd_region_new, 7239 .flags = GENL_ADMIN_PERM, 7240 }, 7241 { 7242 .cmd = DEVLINK_CMD_REGION_DEL, 7243 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7244 .doit = devlink_nl_cmd_region_del, 7245 .flags = GENL_ADMIN_PERM, 7246 }, 7247 { 7248 .cmd = DEVLINK_CMD_REGION_READ, 7249 .validate = GENL_DONT_VALIDATE_STRICT | 7250 GENL_DONT_VALIDATE_DUMP_STRICT, 7251 .dumpit = devlink_nl_cmd_region_read_dumpit, 7252 .flags = GENL_ADMIN_PERM, 7253 }, 7254 { 7255 .cmd = DEVLINK_CMD_INFO_GET, 7256 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7257 .doit = devlink_nl_cmd_info_get_doit, 7258 .dumpit = devlink_nl_cmd_info_get_dumpit, 7259 /* can be retrieved by unprivileged users */ 7260 }, 7261 { 7262 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET, 7263 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7264 .doit = devlink_nl_cmd_health_reporter_get_doit, 7265 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit, 7266 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | 7267 DEVLINK_NL_FLAG_NO_LOCK, 7268 /* can be retrieved by unprivileged users */ 7269 }, 7270 { 7271 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET, 7272 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7273 .doit = devlink_nl_cmd_health_reporter_set_doit, 7274 .flags = GENL_ADMIN_PERM, 7275 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | 7276 DEVLINK_NL_FLAG_NO_LOCK, 7277 }, 7278 { 7279 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER, 7280 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7281 .doit = devlink_nl_cmd_health_reporter_recover_doit, 7282 .flags = GENL_ADMIN_PERM, 7283 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | 7284 DEVLINK_NL_FLAG_NO_LOCK, 7285 }, 7286 { 7287 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 7288 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7289 .doit = devlink_nl_cmd_health_reporter_diagnose_doit, 7290 .flags = GENL_ADMIN_PERM, 7291 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | 7292 DEVLINK_NL_FLAG_NO_LOCK, 7293 }, 7294 { 7295 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 7296 .validate = GENL_DONT_VALIDATE_STRICT | 7297 GENL_DONT_VALIDATE_DUMP_STRICT, 7298 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit, 7299 .flags = GENL_ADMIN_PERM, 7300 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | 7301 DEVLINK_NL_FLAG_NO_LOCK, 7302 }, 7303 { 7304 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, 7305 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7306 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit, 7307 .flags = GENL_ADMIN_PERM, 7308 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | 7309 DEVLINK_NL_FLAG_NO_LOCK, 7310 }, 7311 { 7312 .cmd = DEVLINK_CMD_FLASH_UPDATE, 7313 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 7314 .doit = devlink_nl_cmd_flash_update, 7315 .flags = GENL_ADMIN_PERM, 7316 }, 7317 { 7318 .cmd = DEVLINK_CMD_TRAP_GET, 7319 .doit = devlink_nl_cmd_trap_get_doit, 7320 .dumpit = devlink_nl_cmd_trap_get_dumpit, 7321 /* can be retrieved by unprivileged users */ 7322 }, 7323 { 7324 .cmd = DEVLINK_CMD_TRAP_SET, 7325 .doit = devlink_nl_cmd_trap_set_doit, 7326 .flags = GENL_ADMIN_PERM, 7327 }, 7328 { 7329 .cmd = DEVLINK_CMD_TRAP_GROUP_GET, 7330 .doit = devlink_nl_cmd_trap_group_get_doit, 7331 .dumpit = devlink_nl_cmd_trap_group_get_dumpit, 7332 /* can be retrieved by unprivileged users */ 7333 }, 7334 { 7335 .cmd = DEVLINK_CMD_TRAP_GROUP_SET, 7336 .doit = devlink_nl_cmd_trap_group_set_doit, 7337 .flags = GENL_ADMIN_PERM, 7338 }, 7339 { 7340 .cmd = DEVLINK_CMD_TRAP_POLICER_GET, 7341 .doit = devlink_nl_cmd_trap_policer_get_doit, 7342 .dumpit = devlink_nl_cmd_trap_policer_get_dumpit, 7343 /* can be retrieved by unprivileged users */ 7344 }, 7345 { 7346 .cmd = DEVLINK_CMD_TRAP_POLICER_SET, 7347 .doit = devlink_nl_cmd_trap_policer_set_doit, 7348 .flags = GENL_ADMIN_PERM, 7349 }, 7350}; 7351 7352static struct genl_family devlink_nl_family __ro_after_init = { 7353 .name = DEVLINK_GENL_NAME, 7354 .version = DEVLINK_GENL_VERSION, 7355 .maxattr = DEVLINK_ATTR_MAX, 7356 .policy = devlink_nl_policy, 7357 .netnsok = true, 7358 .pre_doit = devlink_nl_pre_doit, 7359 .post_doit = devlink_nl_post_doit, 7360 .module = THIS_MODULE, 7361 .ops = devlink_nl_ops, 7362 .n_ops = ARRAY_SIZE(devlink_nl_ops), 7363 .mcgrps = devlink_nl_mcgrps, 7364 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 7365}; 7366 7367/** 7368 * devlink_alloc - Allocate new devlink instance resources 7369 * 7370 * @ops: ops 7371 * @priv_size: size of user private data 7372 * 7373 * Allocate new devlink instance resources, including devlink index 7374 * and name. 7375 */ 7376struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 7377{ 7378 struct devlink *devlink; 7379 7380 if (WARN_ON(!ops)) 7381 return NULL; 7382 7383 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 7384 if (!devlink) 7385 return NULL; 7386 devlink->ops = ops; 7387 xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC); 7388 __devlink_net_set(devlink, &init_net); 7389 INIT_LIST_HEAD(&devlink->port_list); 7390 INIT_LIST_HEAD(&devlink->sb_list); 7391 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 7392 INIT_LIST_HEAD(&devlink->resource_list); 7393 INIT_LIST_HEAD(&devlink->param_list); 7394 INIT_LIST_HEAD(&devlink->region_list); 7395 INIT_LIST_HEAD(&devlink->reporter_list); 7396 INIT_LIST_HEAD(&devlink->trap_list); 7397 INIT_LIST_HEAD(&devlink->trap_group_list); 7398 INIT_LIST_HEAD(&devlink->trap_policer_list); 7399 mutex_init(&devlink->lock); 7400 mutex_init(&devlink->reporters_lock); 7401 return devlink; 7402} 7403EXPORT_SYMBOL_GPL(devlink_alloc); 7404 7405/** 7406 * devlink_register - Register devlink instance 7407 * 7408 * @devlink: devlink 7409 * @dev: parent device 7410 */ 7411int devlink_register(struct devlink *devlink, struct device *dev) 7412{ 7413 devlink->dev = dev; 7414 devlink->registered = true; 7415 mutex_lock(&devlink_mutex); 7416 list_add_tail(&devlink->list, &devlink_list); 7417 devlink_notify(devlink, DEVLINK_CMD_NEW); 7418 mutex_unlock(&devlink_mutex); 7419 return 0; 7420} 7421EXPORT_SYMBOL_GPL(devlink_register); 7422 7423/** 7424 * devlink_unregister - Unregister devlink instance 7425 * 7426 * @devlink: devlink 7427 */ 7428void devlink_unregister(struct devlink *devlink) 7429{ 7430 mutex_lock(&devlink_mutex); 7431 WARN_ON(devlink_reload_supported(devlink) && 7432 devlink->reload_enabled); 7433 devlink_notify(devlink, DEVLINK_CMD_DEL); 7434 list_del(&devlink->list); 7435 mutex_unlock(&devlink_mutex); 7436} 7437EXPORT_SYMBOL_GPL(devlink_unregister); 7438 7439/** 7440 * devlink_reload_enable - Enable reload of devlink instance 7441 * 7442 * @devlink: devlink 7443 * 7444 * Should be called at end of device initialization 7445 * process when reload operation is supported. 7446 */ 7447void devlink_reload_enable(struct devlink *devlink) 7448{ 7449 mutex_lock(&devlink_mutex); 7450 devlink->reload_enabled = true; 7451 mutex_unlock(&devlink_mutex); 7452} 7453EXPORT_SYMBOL_GPL(devlink_reload_enable); 7454 7455/** 7456 * devlink_reload_disable - Disable reload of devlink instance 7457 * 7458 * @devlink: devlink 7459 * 7460 * Should be called at the beginning of device cleanup 7461 * process when reload operation is supported. 7462 */ 7463void devlink_reload_disable(struct devlink *devlink) 7464{ 7465 mutex_lock(&devlink_mutex); 7466 /* Mutex is taken which ensures that no reload operation is in 7467 * progress while setting up forbidded flag. 7468 */ 7469 devlink->reload_enabled = false; 7470 mutex_unlock(&devlink_mutex); 7471} 7472EXPORT_SYMBOL_GPL(devlink_reload_disable); 7473 7474/** 7475 * devlink_free - Free devlink instance resources 7476 * 7477 * @devlink: devlink 7478 */ 7479void devlink_free(struct devlink *devlink) 7480{ 7481 mutex_destroy(&devlink->reporters_lock); 7482 mutex_destroy(&devlink->lock); 7483 WARN_ON(!list_empty(&devlink->trap_policer_list)); 7484 WARN_ON(!list_empty(&devlink->trap_group_list)); 7485 WARN_ON(!list_empty(&devlink->trap_list)); 7486 WARN_ON(!list_empty(&devlink->reporter_list)); 7487 WARN_ON(!list_empty(&devlink->region_list)); 7488 WARN_ON(!list_empty(&devlink->param_list)); 7489 WARN_ON(!list_empty(&devlink->resource_list)); 7490 WARN_ON(!list_empty(&devlink->dpipe_table_list)); 7491 WARN_ON(!list_empty(&devlink->sb_list)); 7492 WARN_ON(!list_empty(&devlink->port_list)); 7493 7494 xa_destroy(&devlink->snapshot_ids); 7495 7496 kfree(devlink); 7497} 7498EXPORT_SYMBOL_GPL(devlink_free); 7499 7500static void devlink_port_type_warn(struct work_struct *work) 7501{ 7502 WARN(true, "Type was not set for devlink port."); 7503} 7504 7505static bool devlink_port_type_should_warn(struct devlink_port *devlink_port) 7506{ 7507 /* Ignore CPU and DSA flavours. */ 7508 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU && 7509 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA; 7510} 7511 7512#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600) 7513 7514static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port) 7515{ 7516 if (!devlink_port_type_should_warn(devlink_port)) 7517 return; 7518 /* Schedule a work to WARN in case driver does not set port 7519 * type within timeout. 7520 */ 7521 schedule_delayed_work(&devlink_port->type_warn_dw, 7522 DEVLINK_PORT_TYPE_WARN_TIMEOUT); 7523} 7524 7525static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port) 7526{ 7527 if (!devlink_port_type_should_warn(devlink_port)) 7528 return; 7529 cancel_delayed_work_sync(&devlink_port->type_warn_dw); 7530} 7531 7532/** 7533 * devlink_port_register - Register devlink port 7534 * 7535 * @devlink: devlink 7536 * @devlink_port: devlink port 7537 * @port_index: driver-specific numerical identifier of the port 7538 * 7539 * Register devlink port with provided port index. User can use 7540 * any indexing, even hw-related one. devlink_port structure 7541 * is convenient to be embedded inside user driver private structure. 7542 * Note that the caller should take care of zeroing the devlink_port 7543 * structure. 7544 */ 7545int devlink_port_register(struct devlink *devlink, 7546 struct devlink_port *devlink_port, 7547 unsigned int port_index) 7548{ 7549 mutex_lock(&devlink->lock); 7550 if (devlink_port_index_exists(devlink, port_index)) { 7551 mutex_unlock(&devlink->lock); 7552 return -EEXIST; 7553 } 7554 devlink_port->devlink = devlink; 7555 devlink_port->index = port_index; 7556 devlink_port->registered = true; 7557 spin_lock_init(&devlink_port->type_lock); 7558 list_add_tail(&devlink_port->list, &devlink->port_list); 7559 INIT_LIST_HEAD(&devlink_port->param_list); 7560 mutex_unlock(&devlink->lock); 7561 INIT_LIST_HEAD(&devlink_port->reporter_list); 7562 mutex_init(&devlink_port->reporters_lock); 7563 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn); 7564 devlink_port_type_warn_schedule(devlink_port); 7565 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 7566 return 0; 7567} 7568EXPORT_SYMBOL_GPL(devlink_port_register); 7569 7570/** 7571 * devlink_port_unregister - Unregister devlink port 7572 * 7573 * @devlink_port: devlink port 7574 */ 7575void devlink_port_unregister(struct devlink_port *devlink_port) 7576{ 7577 struct devlink *devlink = devlink_port->devlink; 7578 7579 WARN_ON(!list_empty(&devlink_port->reporter_list)); 7580 mutex_destroy(&devlink_port->reporters_lock); 7581 devlink_port_type_warn_cancel(devlink_port); 7582 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 7583 mutex_lock(&devlink->lock); 7584 list_del(&devlink_port->list); 7585 mutex_unlock(&devlink->lock); 7586} 7587EXPORT_SYMBOL_GPL(devlink_port_unregister); 7588 7589static void __devlink_port_type_set(struct devlink_port *devlink_port, 7590 enum devlink_port_type type, 7591 void *type_dev) 7592{ 7593 if (WARN_ON(!devlink_port->registered)) 7594 return; 7595 devlink_port_type_warn_cancel(devlink_port); 7596 spin_lock_bh(&devlink_port->type_lock); 7597 devlink_port->type = type; 7598 devlink_port->type_dev = type_dev; 7599 spin_unlock_bh(&devlink_port->type_lock); 7600 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 7601} 7602 7603/** 7604 * devlink_port_type_eth_set - Set port type to Ethernet 7605 * 7606 * @devlink_port: devlink port 7607 * @netdev: related netdevice 7608 */ 7609void devlink_port_type_eth_set(struct devlink_port *devlink_port, 7610 struct net_device *netdev) 7611{ 7612 const struct net_device_ops *ops = netdev->netdev_ops; 7613 7614 /* If driver registers devlink port, it should set devlink port 7615 * attributes accordingly so the compat functions are called 7616 * and the original ops are not used. 7617 */ 7618 if (ops->ndo_get_phys_port_name) { 7619 /* Some drivers use the same set of ndos for netdevs 7620 * that have devlink_port registered and also for 7621 * those who don't. Make sure that ndo_get_phys_port_name 7622 * returns -EOPNOTSUPP here in case it is defined. 7623 * Warn if not. 7624 */ 7625 char name[IFNAMSIZ]; 7626 int err; 7627 7628 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name)); 7629 WARN_ON(err != -EOPNOTSUPP); 7630 } 7631 if (ops->ndo_get_port_parent_id) { 7632 /* Some drivers use the same set of ndos for netdevs 7633 * that have devlink_port registered and also for 7634 * those who don't. Make sure that ndo_get_port_parent_id 7635 * returns -EOPNOTSUPP here in case it is defined. 7636 * Warn if not. 7637 */ 7638 struct netdev_phys_item_id ppid; 7639 int err; 7640 7641 err = ops->ndo_get_port_parent_id(netdev, &ppid); 7642 WARN_ON(err != -EOPNOTSUPP); 7643 } 7644 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev); 7645} 7646EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 7647 7648/** 7649 * devlink_port_type_ib_set - Set port type to InfiniBand 7650 * 7651 * @devlink_port: devlink port 7652 * @ibdev: related IB device 7653 */ 7654void devlink_port_type_ib_set(struct devlink_port *devlink_port, 7655 struct ib_device *ibdev) 7656{ 7657 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev); 7658} 7659EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 7660 7661/** 7662 * devlink_port_type_clear - Clear port type 7663 * 7664 * @devlink_port: devlink port 7665 */ 7666void devlink_port_type_clear(struct devlink_port *devlink_port) 7667{ 7668 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL); 7669 devlink_port_type_warn_schedule(devlink_port); 7670} 7671EXPORT_SYMBOL_GPL(devlink_port_type_clear); 7672 7673static int __devlink_port_attrs_set(struct devlink_port *devlink_port, 7674 enum devlink_port_flavour flavour) 7675{ 7676 struct devlink_port_attrs *attrs = &devlink_port->attrs; 7677 7678 if (WARN_ON(devlink_port->registered)) 7679 return -EEXIST; 7680 devlink_port->attrs_set = true; 7681 attrs->flavour = flavour; 7682 if (attrs->switch_id.id_len) { 7683 devlink_port->switch_port = true; 7684 if (WARN_ON(attrs->switch_id.id_len > MAX_PHYS_ITEM_ID_LEN)) 7685 attrs->switch_id.id_len = MAX_PHYS_ITEM_ID_LEN; 7686 } else { 7687 devlink_port->switch_port = false; 7688 } 7689 return 0; 7690} 7691 7692/** 7693 * devlink_port_attrs_set - Set port attributes 7694 * 7695 * @devlink_port: devlink port 7696 * @attrs: devlink port attrs 7697 */ 7698void devlink_port_attrs_set(struct devlink_port *devlink_port, 7699 struct devlink_port_attrs *attrs) 7700{ 7701 int ret; 7702 7703 devlink_port->attrs = *attrs; 7704 ret = __devlink_port_attrs_set(devlink_port, attrs->flavour); 7705 if (ret) 7706 return; 7707 WARN_ON(attrs->splittable && attrs->split); 7708} 7709EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 7710 7711/** 7712 * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes 7713 * 7714 * @devlink_port: devlink port 7715 * @pf: associated PF for the devlink port instance 7716 */ 7717void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u16 pf) 7718{ 7719 struct devlink_port_attrs *attrs = &devlink_port->attrs; 7720 int ret; 7721 7722 ret = __devlink_port_attrs_set(devlink_port, 7723 DEVLINK_PORT_FLAVOUR_PCI_PF); 7724 if (ret) 7725 return; 7726 7727 attrs->pci_pf.pf = pf; 7728} 7729EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set); 7730 7731/** 7732 * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes 7733 * 7734 * @devlink_port: devlink port 7735 * @pf: associated PF for the devlink port instance 7736 * @vf: associated VF of a PF for the devlink port instance 7737 */ 7738void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, 7739 u16 pf, u16 vf) 7740{ 7741 struct devlink_port_attrs *attrs = &devlink_port->attrs; 7742 int ret; 7743 7744 ret = __devlink_port_attrs_set(devlink_port, 7745 DEVLINK_PORT_FLAVOUR_PCI_VF); 7746 if (ret) 7747 return; 7748 attrs->pci_vf.pf = pf; 7749 attrs->pci_vf.vf = vf; 7750} 7751EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); 7752 7753static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, 7754 char *name, size_t len) 7755{ 7756 struct devlink_port_attrs *attrs = &devlink_port->attrs; 7757 int n = 0; 7758 7759 if (!devlink_port->attrs_set) 7760 return -EOPNOTSUPP; 7761 7762 switch (attrs->flavour) { 7763 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 7764 case DEVLINK_PORT_FLAVOUR_VIRTUAL: 7765 if (!attrs->split) 7766 n = snprintf(name, len, "p%u", attrs->phys.port_number); 7767 else 7768 n = snprintf(name, len, "p%us%u", 7769 attrs->phys.port_number, 7770 attrs->phys.split_subport_number); 7771 break; 7772 case DEVLINK_PORT_FLAVOUR_CPU: 7773 case DEVLINK_PORT_FLAVOUR_DSA: 7774 /* As CPU and DSA ports do not have a netdevice associated 7775 * case should not ever happen. 7776 */ 7777 WARN_ON(1); 7778 return -EINVAL; 7779 case DEVLINK_PORT_FLAVOUR_PCI_PF: 7780 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf); 7781 break; 7782 case DEVLINK_PORT_FLAVOUR_PCI_VF: 7783 n = snprintf(name, len, "pf%uvf%u", 7784 attrs->pci_vf.pf, attrs->pci_vf.vf); 7785 break; 7786 } 7787 7788 if (n >= len) 7789 return -EINVAL; 7790 7791 return 0; 7792} 7793 7794int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 7795 u32 size, u16 ingress_pools_count, 7796 u16 egress_pools_count, u16 ingress_tc_count, 7797 u16 egress_tc_count) 7798{ 7799 struct devlink_sb *devlink_sb; 7800 int err = 0; 7801 7802 mutex_lock(&devlink->lock); 7803 if (devlink_sb_index_exists(devlink, sb_index)) { 7804 err = -EEXIST; 7805 goto unlock; 7806 } 7807 7808 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 7809 if (!devlink_sb) { 7810 err = -ENOMEM; 7811 goto unlock; 7812 } 7813 devlink_sb->index = sb_index; 7814 devlink_sb->size = size; 7815 devlink_sb->ingress_pools_count = ingress_pools_count; 7816 devlink_sb->egress_pools_count = egress_pools_count; 7817 devlink_sb->ingress_tc_count = ingress_tc_count; 7818 devlink_sb->egress_tc_count = egress_tc_count; 7819 list_add_tail(&devlink_sb->list, &devlink->sb_list); 7820unlock: 7821 mutex_unlock(&devlink->lock); 7822 return err; 7823} 7824EXPORT_SYMBOL_GPL(devlink_sb_register); 7825 7826void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 7827{ 7828 struct devlink_sb *devlink_sb; 7829 7830 mutex_lock(&devlink->lock); 7831 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 7832 WARN_ON(!devlink_sb); 7833 list_del(&devlink_sb->list); 7834 mutex_unlock(&devlink->lock); 7835 kfree(devlink_sb); 7836} 7837EXPORT_SYMBOL_GPL(devlink_sb_unregister); 7838 7839/** 7840 * devlink_dpipe_headers_register - register dpipe headers 7841 * 7842 * @devlink: devlink 7843 * @dpipe_headers: dpipe header array 7844 * 7845 * Register the headers supported by hardware. 7846 */ 7847int devlink_dpipe_headers_register(struct devlink *devlink, 7848 struct devlink_dpipe_headers *dpipe_headers) 7849{ 7850 mutex_lock(&devlink->lock); 7851 devlink->dpipe_headers = dpipe_headers; 7852 mutex_unlock(&devlink->lock); 7853 return 0; 7854} 7855EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 7856 7857/** 7858 * devlink_dpipe_headers_unregister - unregister dpipe headers 7859 * 7860 * @devlink: devlink 7861 * 7862 * Unregister the headers supported by hardware. 7863 */ 7864void devlink_dpipe_headers_unregister(struct devlink *devlink) 7865{ 7866 mutex_lock(&devlink->lock); 7867 devlink->dpipe_headers = NULL; 7868 mutex_unlock(&devlink->lock); 7869} 7870EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 7871 7872/** 7873 * devlink_dpipe_table_counter_enabled - check if counter allocation 7874 * required 7875 * @devlink: devlink 7876 * @table_name: tables name 7877 * 7878 * Used by driver to check if counter allocation is required. 7879 * After counter allocation is turned on the table entries 7880 * are updated to include counter statistics. 7881 * 7882 * After that point on the driver must respect the counter 7883 * state so that each entry added to the table is added 7884 * with a counter. 7885 */ 7886bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 7887 const char *table_name) 7888{ 7889 struct devlink_dpipe_table *table; 7890 bool enabled; 7891 7892 rcu_read_lock(); 7893 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 7894 table_name, devlink); 7895 enabled = false; 7896 if (table) 7897 enabled = table->counters_enabled; 7898 rcu_read_unlock(); 7899 return enabled; 7900} 7901EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 7902 7903/** 7904 * devlink_dpipe_table_register - register dpipe table 7905 * 7906 * @devlink: devlink 7907 * @table_name: table name 7908 * @table_ops: table ops 7909 * @priv: priv 7910 * @counter_control_extern: external control for counters 7911 */ 7912int devlink_dpipe_table_register(struct devlink *devlink, 7913 const char *table_name, 7914 struct devlink_dpipe_table_ops *table_ops, 7915 void *priv, bool counter_control_extern) 7916{ 7917 struct devlink_dpipe_table *table; 7918 int err = 0; 7919 7920 if (WARN_ON(!table_ops->size_get)) 7921 return -EINVAL; 7922 7923 mutex_lock(&devlink->lock); 7924 7925 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name, 7926 devlink)) { 7927 err = -EEXIST; 7928 goto unlock; 7929 } 7930 7931 table = kzalloc(sizeof(*table), GFP_KERNEL); 7932 if (!table) { 7933 err = -ENOMEM; 7934 goto unlock; 7935 } 7936 7937 table->name = table_name; 7938 table->table_ops = table_ops; 7939 table->priv = priv; 7940 table->counter_control_extern = counter_control_extern; 7941 7942 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 7943unlock: 7944 mutex_unlock(&devlink->lock); 7945 return err; 7946} 7947EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 7948 7949/** 7950 * devlink_dpipe_table_unregister - unregister dpipe table 7951 * 7952 * @devlink: devlink 7953 * @table_name: table name 7954 */ 7955void devlink_dpipe_table_unregister(struct devlink *devlink, 7956 const char *table_name) 7957{ 7958 struct devlink_dpipe_table *table; 7959 7960 mutex_lock(&devlink->lock); 7961 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 7962 table_name, devlink); 7963 if (!table) 7964 goto unlock; 7965 list_del_rcu(&table->list); 7966 mutex_unlock(&devlink->lock); 7967 kfree_rcu(table, rcu); 7968 return; 7969unlock: 7970 mutex_unlock(&devlink->lock); 7971} 7972EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 7973 7974/** 7975 * devlink_resource_register - devlink resource register 7976 * 7977 * @devlink: devlink 7978 * @resource_name: resource's name 7979 * @resource_size: resource's size 7980 * @resource_id: resource's id 7981 * @parent_resource_id: resource's parent id 7982 * @size_params: size parameters 7983 */ 7984int devlink_resource_register(struct devlink *devlink, 7985 const char *resource_name, 7986 u64 resource_size, 7987 u64 resource_id, 7988 u64 parent_resource_id, 7989 const struct devlink_resource_size_params *size_params) 7990{ 7991 struct devlink_resource *resource; 7992 struct list_head *resource_list; 7993 bool top_hierarchy; 7994 int err = 0; 7995 7996 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 7997 7998 mutex_lock(&devlink->lock); 7999 resource = devlink_resource_find(devlink, NULL, resource_id); 8000 if (resource) { 8001 err = -EINVAL; 8002 goto out; 8003 } 8004 8005 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 8006 if (!resource) { 8007 err = -ENOMEM; 8008 goto out; 8009 } 8010 8011 if (top_hierarchy) { 8012 resource_list = &devlink->resource_list; 8013 } else { 8014 struct devlink_resource *parent_resource; 8015 8016 parent_resource = devlink_resource_find(devlink, NULL, 8017 parent_resource_id); 8018 if (parent_resource) { 8019 resource_list = &parent_resource->resource_list; 8020 resource->parent = parent_resource; 8021 } else { 8022 kfree(resource); 8023 err = -EINVAL; 8024 goto out; 8025 } 8026 } 8027 8028 resource->name = resource_name; 8029 resource->size = resource_size; 8030 resource->size_new = resource_size; 8031 resource->id = resource_id; 8032 resource->size_valid = true; 8033 memcpy(&resource->size_params, size_params, 8034 sizeof(resource->size_params)); 8035 INIT_LIST_HEAD(&resource->resource_list); 8036 list_add_tail(&resource->list, resource_list); 8037out: 8038 mutex_unlock(&devlink->lock); 8039 return err; 8040} 8041EXPORT_SYMBOL_GPL(devlink_resource_register); 8042 8043/** 8044 * devlink_resources_unregister - free all resources 8045 * 8046 * @devlink: devlink 8047 * @resource: resource 8048 */ 8049void devlink_resources_unregister(struct devlink *devlink, 8050 struct devlink_resource *resource) 8051{ 8052 struct devlink_resource *tmp, *child_resource; 8053 struct list_head *resource_list; 8054 8055 if (resource) 8056 resource_list = &resource->resource_list; 8057 else 8058 resource_list = &devlink->resource_list; 8059 8060 if (!resource) 8061 mutex_lock(&devlink->lock); 8062 8063 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 8064 devlink_resources_unregister(devlink, child_resource); 8065 list_del(&child_resource->list); 8066 kfree(child_resource); 8067 } 8068 8069 if (!resource) 8070 mutex_unlock(&devlink->lock); 8071} 8072EXPORT_SYMBOL_GPL(devlink_resources_unregister); 8073 8074/** 8075 * devlink_resource_size_get - get and update size 8076 * 8077 * @devlink: devlink 8078 * @resource_id: the requested resource id 8079 * @p_resource_size: ptr to update 8080 */ 8081int devlink_resource_size_get(struct devlink *devlink, 8082 u64 resource_id, 8083 u64 *p_resource_size) 8084{ 8085 struct devlink_resource *resource; 8086 int err = 0; 8087 8088 mutex_lock(&devlink->lock); 8089 resource = devlink_resource_find(devlink, NULL, resource_id); 8090 if (!resource) { 8091 err = -EINVAL; 8092 goto out; 8093 } 8094 *p_resource_size = resource->size_new; 8095 resource->size = resource->size_new; 8096out: 8097 mutex_unlock(&devlink->lock); 8098 return err; 8099} 8100EXPORT_SYMBOL_GPL(devlink_resource_size_get); 8101 8102/** 8103 * devlink_dpipe_table_resource_set - set the resource id 8104 * 8105 * @devlink: devlink 8106 * @table_name: table name 8107 * @resource_id: resource id 8108 * @resource_units: number of resource's units consumed per table's entry 8109 */ 8110int devlink_dpipe_table_resource_set(struct devlink *devlink, 8111 const char *table_name, u64 resource_id, 8112 u64 resource_units) 8113{ 8114 struct devlink_dpipe_table *table; 8115 int err = 0; 8116 8117 mutex_lock(&devlink->lock); 8118 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 8119 table_name, devlink); 8120 if (!table) { 8121 err = -EINVAL; 8122 goto out; 8123 } 8124 table->resource_id = resource_id; 8125 table->resource_units = resource_units; 8126 table->resource_valid = true; 8127out: 8128 mutex_unlock(&devlink->lock); 8129 return err; 8130} 8131EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 8132 8133/** 8134 * devlink_resource_occ_get_register - register occupancy getter 8135 * 8136 * @devlink: devlink 8137 * @resource_id: resource id 8138 * @occ_get: occupancy getter callback 8139 * @occ_get_priv: occupancy getter callback priv 8140 */ 8141void devlink_resource_occ_get_register(struct devlink *devlink, 8142 u64 resource_id, 8143 devlink_resource_occ_get_t *occ_get, 8144 void *occ_get_priv) 8145{ 8146 struct devlink_resource *resource; 8147 8148 mutex_lock(&devlink->lock); 8149 resource = devlink_resource_find(devlink, NULL, resource_id); 8150 if (WARN_ON(!resource)) 8151 goto out; 8152 WARN_ON(resource->occ_get); 8153 8154 resource->occ_get = occ_get; 8155 resource->occ_get_priv = occ_get_priv; 8156out: 8157 mutex_unlock(&devlink->lock); 8158} 8159EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 8160 8161/** 8162 * devlink_resource_occ_get_unregister - unregister occupancy getter 8163 * 8164 * @devlink: devlink 8165 * @resource_id: resource id 8166 */ 8167void devlink_resource_occ_get_unregister(struct devlink *devlink, 8168 u64 resource_id) 8169{ 8170 struct devlink_resource *resource; 8171 8172 mutex_lock(&devlink->lock); 8173 resource = devlink_resource_find(devlink, NULL, resource_id); 8174 if (WARN_ON(!resource)) 8175 goto out; 8176 WARN_ON(!resource->occ_get); 8177 8178 resource->occ_get = NULL; 8179 resource->occ_get_priv = NULL; 8180out: 8181 mutex_unlock(&devlink->lock); 8182} 8183EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 8184 8185static int devlink_param_verify(const struct devlink_param *param) 8186{ 8187 if (!param || !param->name || !param->supported_cmodes) 8188 return -EINVAL; 8189 if (param->generic) 8190 return devlink_param_generic_verify(param); 8191 else 8192 return devlink_param_driver_verify(param); 8193} 8194 8195static int __devlink_params_register(struct devlink *devlink, 8196 unsigned int port_index, 8197 struct list_head *param_list, 8198 const struct devlink_param *params, 8199 size_t params_count, 8200 enum devlink_command reg_cmd, 8201 enum devlink_command unreg_cmd) 8202{ 8203 const struct devlink_param *param = params; 8204 int i; 8205 int err; 8206 8207 mutex_lock(&devlink->lock); 8208 for (i = 0; i < params_count; i++, param++) { 8209 err = devlink_param_verify(param); 8210 if (err) 8211 goto rollback; 8212 8213 err = devlink_param_register_one(devlink, port_index, 8214 param_list, param, reg_cmd); 8215 if (err) 8216 goto rollback; 8217 } 8218 8219 mutex_unlock(&devlink->lock); 8220 return 0; 8221 8222rollback: 8223 if (!i) 8224 goto unlock; 8225 for (param--; i > 0; i--, param--) 8226 devlink_param_unregister_one(devlink, port_index, param_list, 8227 param, unreg_cmd); 8228unlock: 8229 mutex_unlock(&devlink->lock); 8230 return err; 8231} 8232 8233static void __devlink_params_unregister(struct devlink *devlink, 8234 unsigned int port_index, 8235 struct list_head *param_list, 8236 const struct devlink_param *params, 8237 size_t params_count, 8238 enum devlink_command cmd) 8239{ 8240 const struct devlink_param *param = params; 8241 int i; 8242 8243 mutex_lock(&devlink->lock); 8244 for (i = 0; i < params_count; i++, param++) 8245 devlink_param_unregister_one(devlink, 0, param_list, param, 8246 cmd); 8247 mutex_unlock(&devlink->lock); 8248} 8249 8250/** 8251 * devlink_params_register - register configuration parameters 8252 * 8253 * @devlink: devlink 8254 * @params: configuration parameters array 8255 * @params_count: number of parameters provided 8256 * 8257 * Register the configuration parameters supported by the driver. 8258 */ 8259int devlink_params_register(struct devlink *devlink, 8260 const struct devlink_param *params, 8261 size_t params_count) 8262{ 8263 return __devlink_params_register(devlink, 0, &devlink->param_list, 8264 params, params_count, 8265 DEVLINK_CMD_PARAM_NEW, 8266 DEVLINK_CMD_PARAM_DEL); 8267} 8268EXPORT_SYMBOL_GPL(devlink_params_register); 8269 8270/** 8271 * devlink_params_unregister - unregister configuration parameters 8272 * @devlink: devlink 8273 * @params: configuration parameters to unregister 8274 * @params_count: number of parameters provided 8275 */ 8276void devlink_params_unregister(struct devlink *devlink, 8277 const struct devlink_param *params, 8278 size_t params_count) 8279{ 8280 return __devlink_params_unregister(devlink, 0, &devlink->param_list, 8281 params, params_count, 8282 DEVLINK_CMD_PARAM_DEL); 8283} 8284EXPORT_SYMBOL_GPL(devlink_params_unregister); 8285 8286/** 8287 * devlink_params_publish - publish configuration parameters 8288 * 8289 * @devlink: devlink 8290 * 8291 * Publish previously registered configuration parameters. 8292 */ 8293void devlink_params_publish(struct devlink *devlink) 8294{ 8295 struct devlink_param_item *param_item; 8296 8297 list_for_each_entry(param_item, &devlink->param_list, list) { 8298 if (param_item->published) 8299 continue; 8300 param_item->published = true; 8301 devlink_param_notify(devlink, 0, param_item, 8302 DEVLINK_CMD_PARAM_NEW); 8303 } 8304} 8305EXPORT_SYMBOL_GPL(devlink_params_publish); 8306 8307/** 8308 * devlink_params_unpublish - unpublish configuration parameters 8309 * 8310 * @devlink: devlink 8311 * 8312 * Unpublish previously registered configuration parameters. 8313 */ 8314void devlink_params_unpublish(struct devlink *devlink) 8315{ 8316 struct devlink_param_item *param_item; 8317 8318 list_for_each_entry(param_item, &devlink->param_list, list) { 8319 if (!param_item->published) 8320 continue; 8321 param_item->published = false; 8322 devlink_param_notify(devlink, 0, param_item, 8323 DEVLINK_CMD_PARAM_DEL); 8324 } 8325} 8326EXPORT_SYMBOL_GPL(devlink_params_unpublish); 8327 8328/** 8329 * devlink_port_params_register - register port configuration parameters 8330 * 8331 * @devlink_port: devlink port 8332 * @params: configuration parameters array 8333 * @params_count: number of parameters provided 8334 * 8335 * Register the configuration parameters supported by the port. 8336 */ 8337int devlink_port_params_register(struct devlink_port *devlink_port, 8338 const struct devlink_param *params, 8339 size_t params_count) 8340{ 8341 return __devlink_params_register(devlink_port->devlink, 8342 devlink_port->index, 8343 &devlink_port->param_list, params, 8344 params_count, 8345 DEVLINK_CMD_PORT_PARAM_NEW, 8346 DEVLINK_CMD_PORT_PARAM_DEL); 8347} 8348EXPORT_SYMBOL_GPL(devlink_port_params_register); 8349 8350/** 8351 * devlink_port_params_unregister - unregister port configuration 8352 * parameters 8353 * 8354 * @devlink_port: devlink port 8355 * @params: configuration parameters array 8356 * @params_count: number of parameters provided 8357 */ 8358void devlink_port_params_unregister(struct devlink_port *devlink_port, 8359 const struct devlink_param *params, 8360 size_t params_count) 8361{ 8362 return __devlink_params_unregister(devlink_port->devlink, 8363 devlink_port->index, 8364 &devlink_port->param_list, 8365 params, params_count, 8366 DEVLINK_CMD_PORT_PARAM_DEL); 8367} 8368EXPORT_SYMBOL_GPL(devlink_port_params_unregister); 8369 8370static int 8371__devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id, 8372 union devlink_param_value *init_val) 8373{ 8374 struct devlink_param_item *param_item; 8375 8376 param_item = devlink_param_find_by_id(param_list, param_id); 8377 if (!param_item) 8378 return -EINVAL; 8379 8380 if (!param_item->driverinit_value_valid || 8381 !devlink_param_cmode_is_supported(param_item->param, 8382 DEVLINK_PARAM_CMODE_DRIVERINIT)) 8383 return -EOPNOTSUPP; 8384 8385 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 8386 strcpy(init_val->vstr, param_item->driverinit_value.vstr); 8387 else 8388 *init_val = param_item->driverinit_value; 8389 8390 return 0; 8391} 8392 8393static int 8394__devlink_param_driverinit_value_set(struct devlink *devlink, 8395 unsigned int port_index, 8396 struct list_head *param_list, u32 param_id, 8397 union devlink_param_value init_val, 8398 enum devlink_command cmd) 8399{ 8400 struct devlink_param_item *param_item; 8401 8402 param_item = devlink_param_find_by_id(param_list, param_id); 8403 if (!param_item) 8404 return -EINVAL; 8405 8406 if (!devlink_param_cmode_is_supported(param_item->param, 8407 DEVLINK_PARAM_CMODE_DRIVERINIT)) 8408 return -EOPNOTSUPP; 8409 8410 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 8411 strcpy(param_item->driverinit_value.vstr, init_val.vstr); 8412 else 8413 param_item->driverinit_value = init_val; 8414 param_item->driverinit_value_valid = true; 8415 8416 devlink_param_notify(devlink, port_index, param_item, cmd); 8417 return 0; 8418} 8419 8420/** 8421 * devlink_param_driverinit_value_get - get configuration parameter 8422 * value for driver initializing 8423 * 8424 * @devlink: devlink 8425 * @param_id: parameter ID 8426 * @init_val: value of parameter in driverinit configuration mode 8427 * 8428 * This function should be used by the driver to get driverinit 8429 * configuration for initialization after reload command. 8430 */ 8431int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 8432 union devlink_param_value *init_val) 8433{ 8434 if (!devlink_reload_supported(devlink)) 8435 return -EOPNOTSUPP; 8436 8437 return __devlink_param_driverinit_value_get(&devlink->param_list, 8438 param_id, init_val); 8439} 8440EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 8441 8442/** 8443 * devlink_param_driverinit_value_set - set value of configuration 8444 * parameter for driverinit 8445 * configuration mode 8446 * 8447 * @devlink: devlink 8448 * @param_id: parameter ID 8449 * @init_val: value of parameter to set for driverinit configuration mode 8450 * 8451 * This function should be used by the driver to set driverinit 8452 * configuration mode default value. 8453 */ 8454int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 8455 union devlink_param_value init_val) 8456{ 8457 return __devlink_param_driverinit_value_set(devlink, 0, 8458 &devlink->param_list, 8459 param_id, init_val, 8460 DEVLINK_CMD_PARAM_NEW); 8461} 8462EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 8463 8464/** 8465 * devlink_port_param_driverinit_value_get - get configuration parameter 8466 * value for driver initializing 8467 * 8468 * @devlink_port: devlink_port 8469 * @param_id: parameter ID 8470 * @init_val: value of parameter in driverinit configuration mode 8471 * 8472 * This function should be used by the driver to get driverinit 8473 * configuration for initialization after reload command. 8474 */ 8475int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port, 8476 u32 param_id, 8477 union devlink_param_value *init_val) 8478{ 8479 struct devlink *devlink = devlink_port->devlink; 8480 8481 if (!devlink_reload_supported(devlink)) 8482 return -EOPNOTSUPP; 8483 8484 return __devlink_param_driverinit_value_get(&devlink_port->param_list, 8485 param_id, init_val); 8486} 8487EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get); 8488 8489/** 8490 * devlink_port_param_driverinit_value_set - set value of configuration 8491 * parameter for driverinit 8492 * configuration mode 8493 * 8494 * @devlink_port: devlink_port 8495 * @param_id: parameter ID 8496 * @init_val: value of parameter to set for driverinit configuration mode 8497 * 8498 * This function should be used by the driver to set driverinit 8499 * configuration mode default value. 8500 */ 8501int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port, 8502 u32 param_id, 8503 union devlink_param_value init_val) 8504{ 8505 return __devlink_param_driverinit_value_set(devlink_port->devlink, 8506 devlink_port->index, 8507 &devlink_port->param_list, 8508 param_id, init_val, 8509 DEVLINK_CMD_PORT_PARAM_NEW); 8510} 8511EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set); 8512 8513/** 8514 * devlink_param_value_changed - notify devlink on a parameter's value 8515 * change. Should be called by the driver 8516 * right after the change. 8517 * 8518 * @devlink: devlink 8519 * @param_id: parameter ID 8520 * 8521 * This function should be used by the driver to notify devlink on value 8522 * change, excluding driverinit configuration mode. 8523 * For driverinit configuration mode driver should use the function 8524 */ 8525void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 8526{ 8527 struct devlink_param_item *param_item; 8528 8529 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 8530 WARN_ON(!param_item); 8531 8532 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 8533} 8534EXPORT_SYMBOL_GPL(devlink_param_value_changed); 8535 8536/** 8537 * devlink_port_param_value_changed - notify devlink on a parameter's value 8538 * change. Should be called by the driver 8539 * right after the change. 8540 * 8541 * @devlink_port: devlink_port 8542 * @param_id: parameter ID 8543 * 8544 * This function should be used by the driver to notify devlink on value 8545 * change, excluding driverinit configuration mode. 8546 * For driverinit configuration mode driver should use the function 8547 * devlink_port_param_driverinit_value_set() instead. 8548 */ 8549void devlink_port_param_value_changed(struct devlink_port *devlink_port, 8550 u32 param_id) 8551{ 8552 struct devlink_param_item *param_item; 8553 8554 param_item = devlink_param_find_by_id(&devlink_port->param_list, 8555 param_id); 8556 WARN_ON(!param_item); 8557 8558 devlink_param_notify(devlink_port->devlink, devlink_port->index, 8559 param_item, DEVLINK_CMD_PORT_PARAM_NEW); 8560} 8561EXPORT_SYMBOL_GPL(devlink_port_param_value_changed); 8562 8563/** 8564 * devlink_param_value_str_fill - Safely fill-up the string preventing 8565 * from overflow of the preallocated buffer 8566 * 8567 * @dst_val: destination devlink_param_value 8568 * @src: source buffer 8569 */ 8570void devlink_param_value_str_fill(union devlink_param_value *dst_val, 8571 const char *src) 8572{ 8573 size_t len; 8574 8575 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE); 8576 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE); 8577} 8578EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); 8579 8580/** 8581 * devlink_region_create - create a new address region 8582 * 8583 * @devlink: devlink 8584 * @ops: region operations and name 8585 * @region_max_snapshots: Maximum supported number of snapshots for region 8586 * @region_size: size of region 8587 */ 8588struct devlink_region * 8589devlink_region_create(struct devlink *devlink, 8590 const struct devlink_region_ops *ops, 8591 u32 region_max_snapshots, u64 region_size) 8592{ 8593 struct devlink_region *region; 8594 int err = 0; 8595 8596 if (WARN_ON(!ops) || WARN_ON(!ops->destructor)) 8597 return ERR_PTR(-EINVAL); 8598 8599 mutex_lock(&devlink->lock); 8600 8601 if (devlink_region_get_by_name(devlink, ops->name)) { 8602 err = -EEXIST; 8603 goto unlock; 8604 } 8605 8606 region = kzalloc(sizeof(*region), GFP_KERNEL); 8607 if (!region) { 8608 err = -ENOMEM; 8609 goto unlock; 8610 } 8611 8612 region->devlink = devlink; 8613 region->max_snapshots = region_max_snapshots; 8614 region->ops = ops; 8615 region->size = region_size; 8616 INIT_LIST_HEAD(&region->snapshot_list); 8617 list_add_tail(&region->list, &devlink->region_list); 8618 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 8619 8620 mutex_unlock(&devlink->lock); 8621 return region; 8622 8623unlock: 8624 mutex_unlock(&devlink->lock); 8625 return ERR_PTR(err); 8626} 8627EXPORT_SYMBOL_GPL(devlink_region_create); 8628 8629/** 8630 * devlink_region_destroy - destroy address region 8631 * 8632 * @region: devlink region to destroy 8633 */ 8634void devlink_region_destroy(struct devlink_region *region) 8635{ 8636 struct devlink *devlink = region->devlink; 8637 struct devlink_snapshot *snapshot, *ts; 8638 8639 mutex_lock(&devlink->lock); 8640 8641 /* Free all snapshots of region */ 8642 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 8643 devlink_region_snapshot_del(region, snapshot); 8644 8645 list_del(&region->list); 8646 8647 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 8648 mutex_unlock(&devlink->lock); 8649 kfree(region); 8650} 8651EXPORT_SYMBOL_GPL(devlink_region_destroy); 8652 8653/** 8654 * devlink_region_snapshot_id_get - get snapshot ID 8655 * 8656 * This callback should be called when adding a new snapshot, 8657 * Driver should use the same id for multiple snapshots taken 8658 * on multiple regions at the same time/by the same trigger. 8659 * 8660 * The caller of this function must use devlink_region_snapshot_id_put 8661 * when finished creating regions using this id. 8662 * 8663 * Returns zero on success, or a negative error code on failure. 8664 * 8665 * @devlink: devlink 8666 * @id: storage to return id 8667 */ 8668int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) 8669{ 8670 int err; 8671 8672 mutex_lock(&devlink->lock); 8673 err = __devlink_region_snapshot_id_get(devlink, id); 8674 mutex_unlock(&devlink->lock); 8675 8676 return err; 8677} 8678EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get); 8679 8680/** 8681 * devlink_region_snapshot_id_put - put snapshot ID reference 8682 * 8683 * This should be called by a driver after finishing creating snapshots 8684 * with an id. Doing so ensures that the ID can later be released in the 8685 * event that all snapshots using it have been destroyed. 8686 * 8687 * @devlink: devlink 8688 * @id: id to release reference on 8689 */ 8690void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id) 8691{ 8692 mutex_lock(&devlink->lock); 8693 __devlink_snapshot_id_decrement(devlink, id); 8694 mutex_unlock(&devlink->lock); 8695} 8696EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put); 8697 8698/** 8699 * devlink_region_snapshot_create - create a new snapshot 8700 * This will add a new snapshot of a region. The snapshot 8701 * will be stored on the region struct and can be accessed 8702 * from devlink. This is useful for future analyses of snapshots. 8703 * Multiple snapshots can be created on a region. 8704 * The @snapshot_id should be obtained using the getter function. 8705 * 8706 * @region: devlink region of the snapshot 8707 * @data: snapshot data 8708 * @snapshot_id: snapshot id to be created 8709 */ 8710int devlink_region_snapshot_create(struct devlink_region *region, 8711 u8 *data, u32 snapshot_id) 8712{ 8713 struct devlink *devlink = region->devlink; 8714 int err; 8715 8716 mutex_lock(&devlink->lock); 8717 err = __devlink_region_snapshot_create(region, data, snapshot_id); 8718 mutex_unlock(&devlink->lock); 8719 8720 return err; 8721} 8722EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 8723 8724#define DEVLINK_TRAP(_id, _type) \ 8725 { \ 8726 .type = DEVLINK_TRAP_TYPE_##_type, \ 8727 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \ 8728 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \ 8729 } 8730 8731static const struct devlink_trap devlink_trap_generic[] = { 8732 DEVLINK_TRAP(SMAC_MC, DROP), 8733 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP), 8734 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP), 8735 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP), 8736 DEVLINK_TRAP(EMPTY_TX_LIST, DROP), 8737 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP), 8738 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP), 8739 DEVLINK_TRAP(TTL_ERROR, EXCEPTION), 8740 DEVLINK_TRAP(TAIL_DROP, DROP), 8741 DEVLINK_TRAP(NON_IP_PACKET, DROP), 8742 DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP), 8743 DEVLINK_TRAP(DIP_LB, DROP), 8744 DEVLINK_TRAP(SIP_MC, DROP), 8745 DEVLINK_TRAP(SIP_LB, DROP), 8746 DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP), 8747 DEVLINK_TRAP(IPV4_SIP_BC, DROP), 8748 DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP), 8749 DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP), 8750 DEVLINK_TRAP(MTU_ERROR, EXCEPTION), 8751 DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION), 8752 DEVLINK_TRAP(RPF, EXCEPTION), 8753 DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION), 8754 DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION), 8755 DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION), 8756 DEVLINK_TRAP(NON_ROUTABLE, DROP), 8757 DEVLINK_TRAP(DECAP_ERROR, EXCEPTION), 8758 DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP), 8759 DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP), 8760 DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP), 8761 DEVLINK_TRAP(STP, CONTROL), 8762 DEVLINK_TRAP(LACP, CONTROL), 8763 DEVLINK_TRAP(LLDP, CONTROL), 8764 DEVLINK_TRAP(IGMP_QUERY, CONTROL), 8765 DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL), 8766 DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL), 8767 DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL), 8768 DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL), 8769 DEVLINK_TRAP(MLD_QUERY, CONTROL), 8770 DEVLINK_TRAP(MLD_V1_REPORT, CONTROL), 8771 DEVLINK_TRAP(MLD_V2_REPORT, CONTROL), 8772 DEVLINK_TRAP(MLD_V1_DONE, CONTROL), 8773 DEVLINK_TRAP(IPV4_DHCP, CONTROL), 8774 DEVLINK_TRAP(IPV6_DHCP, CONTROL), 8775 DEVLINK_TRAP(ARP_REQUEST, CONTROL), 8776 DEVLINK_TRAP(ARP_RESPONSE, CONTROL), 8777 DEVLINK_TRAP(ARP_OVERLAY, CONTROL), 8778 DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL), 8779 DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL), 8780 DEVLINK_TRAP(IPV4_BFD, CONTROL), 8781 DEVLINK_TRAP(IPV6_BFD, CONTROL), 8782 DEVLINK_TRAP(IPV4_OSPF, CONTROL), 8783 DEVLINK_TRAP(IPV6_OSPF, CONTROL), 8784 DEVLINK_TRAP(IPV4_BGP, CONTROL), 8785 DEVLINK_TRAP(IPV6_BGP, CONTROL), 8786 DEVLINK_TRAP(IPV4_VRRP, CONTROL), 8787 DEVLINK_TRAP(IPV6_VRRP, CONTROL), 8788 DEVLINK_TRAP(IPV4_PIM, CONTROL), 8789 DEVLINK_TRAP(IPV6_PIM, CONTROL), 8790 DEVLINK_TRAP(UC_LB, CONTROL), 8791 DEVLINK_TRAP(LOCAL_ROUTE, CONTROL), 8792 DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL), 8793 DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL), 8794 DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL), 8795 DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL), 8796 DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL), 8797 DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL), 8798 DEVLINK_TRAP(IPV6_REDIRECT, CONTROL), 8799 DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL), 8800 DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL), 8801 DEVLINK_TRAP(PTP_EVENT, CONTROL), 8802 DEVLINK_TRAP(PTP_GENERAL, CONTROL), 8803 DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL), 8804 DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL), 8805 DEVLINK_TRAP(EARLY_DROP, DROP), 8806}; 8807 8808#define DEVLINK_TRAP_GROUP(_id) \ 8809 { \ 8810 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \ 8811 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \ 8812 } 8813 8814static const struct devlink_trap_group devlink_trap_group_generic[] = { 8815 DEVLINK_TRAP_GROUP(L2_DROPS), 8816 DEVLINK_TRAP_GROUP(L3_DROPS), 8817 DEVLINK_TRAP_GROUP(L3_EXCEPTIONS), 8818 DEVLINK_TRAP_GROUP(BUFFER_DROPS), 8819 DEVLINK_TRAP_GROUP(TUNNEL_DROPS), 8820 DEVLINK_TRAP_GROUP(ACL_DROPS), 8821 DEVLINK_TRAP_GROUP(STP), 8822 DEVLINK_TRAP_GROUP(LACP), 8823 DEVLINK_TRAP_GROUP(LLDP), 8824 DEVLINK_TRAP_GROUP(MC_SNOOPING), 8825 DEVLINK_TRAP_GROUP(DHCP), 8826 DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY), 8827 DEVLINK_TRAP_GROUP(BFD), 8828 DEVLINK_TRAP_GROUP(OSPF), 8829 DEVLINK_TRAP_GROUP(BGP), 8830 DEVLINK_TRAP_GROUP(VRRP), 8831 DEVLINK_TRAP_GROUP(PIM), 8832 DEVLINK_TRAP_GROUP(UC_LB), 8833 DEVLINK_TRAP_GROUP(LOCAL_DELIVERY), 8834 DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY), 8835 DEVLINK_TRAP_GROUP(IPV6), 8836 DEVLINK_TRAP_GROUP(PTP_EVENT), 8837 DEVLINK_TRAP_GROUP(PTP_GENERAL), 8838 DEVLINK_TRAP_GROUP(ACL_SAMPLE), 8839 DEVLINK_TRAP_GROUP(ACL_TRAP), 8840}; 8841 8842static int devlink_trap_generic_verify(const struct devlink_trap *trap) 8843{ 8844 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX) 8845 return -EINVAL; 8846 8847 if (strcmp(trap->name, devlink_trap_generic[trap->id].name)) 8848 return -EINVAL; 8849 8850 if (trap->type != devlink_trap_generic[trap->id].type) 8851 return -EINVAL; 8852 8853 return 0; 8854} 8855 8856static int devlink_trap_driver_verify(const struct devlink_trap *trap) 8857{ 8858 int i; 8859 8860 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX) 8861 return -EINVAL; 8862 8863 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) { 8864 if (!strcmp(trap->name, devlink_trap_generic[i].name)) 8865 return -EEXIST; 8866 } 8867 8868 return 0; 8869} 8870 8871static int devlink_trap_verify(const struct devlink_trap *trap) 8872{ 8873 if (!trap || !trap->name) 8874 return -EINVAL; 8875 8876 if (trap->generic) 8877 return devlink_trap_generic_verify(trap); 8878 else 8879 return devlink_trap_driver_verify(trap); 8880} 8881 8882static int 8883devlink_trap_group_generic_verify(const struct devlink_trap_group *group) 8884{ 8885 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 8886 return -EINVAL; 8887 8888 if (strcmp(group->name, devlink_trap_group_generic[group->id].name)) 8889 return -EINVAL; 8890 8891 return 0; 8892} 8893 8894static int 8895devlink_trap_group_driver_verify(const struct devlink_trap_group *group) 8896{ 8897 int i; 8898 8899 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 8900 return -EINVAL; 8901 8902 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) { 8903 if (!strcmp(group->name, devlink_trap_group_generic[i].name)) 8904 return -EEXIST; 8905 } 8906 8907 return 0; 8908} 8909 8910static int devlink_trap_group_verify(const struct devlink_trap_group *group) 8911{ 8912 if (group->generic) 8913 return devlink_trap_group_generic_verify(group); 8914 else 8915 return devlink_trap_group_driver_verify(group); 8916} 8917 8918static void 8919devlink_trap_group_notify(struct devlink *devlink, 8920 const struct devlink_trap_group_item *group_item, 8921 enum devlink_command cmd) 8922{ 8923 struct sk_buff *msg; 8924 int err; 8925 8926 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW && 8927 cmd != DEVLINK_CMD_TRAP_GROUP_DEL); 8928 8929 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 8930 if (!msg) 8931 return; 8932 8933 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0, 8934 0); 8935 if (err) { 8936 nlmsg_free(msg); 8937 return; 8938 } 8939 8940 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 8941 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 8942} 8943 8944static int 8945devlink_trap_item_group_link(struct devlink *devlink, 8946 struct devlink_trap_item *trap_item) 8947{ 8948 u16 group_id = trap_item->trap->init_group_id; 8949 struct devlink_trap_group_item *group_item; 8950 8951 group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id); 8952 if (WARN_ON_ONCE(!group_item)) 8953 return -EINVAL; 8954 8955 trap_item->group_item = group_item; 8956 8957 return 0; 8958} 8959 8960static void devlink_trap_notify(struct devlink *devlink, 8961 const struct devlink_trap_item *trap_item, 8962 enum devlink_command cmd) 8963{ 8964 struct sk_buff *msg; 8965 int err; 8966 8967 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW && 8968 cmd != DEVLINK_CMD_TRAP_DEL); 8969 8970 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 8971 if (!msg) 8972 return; 8973 8974 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0); 8975 if (err) { 8976 nlmsg_free(msg); 8977 return; 8978 } 8979 8980 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 8981 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 8982} 8983 8984static int 8985devlink_trap_register(struct devlink *devlink, 8986 const struct devlink_trap *trap, void *priv) 8987{ 8988 struct devlink_trap_item *trap_item; 8989 int err; 8990 8991 if (devlink_trap_item_lookup(devlink, trap->name)) 8992 return -EEXIST; 8993 8994 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL); 8995 if (!trap_item) 8996 return -ENOMEM; 8997 8998 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 8999 if (!trap_item->stats) { 9000 err = -ENOMEM; 9001 goto err_stats_alloc; 9002 } 9003 9004 trap_item->trap = trap; 9005 trap_item->action = trap->init_action; 9006 trap_item->priv = priv; 9007 9008 err = devlink_trap_item_group_link(devlink, trap_item); 9009 if (err) 9010 goto err_group_link; 9011 9012 err = devlink->ops->trap_init(devlink, trap, trap_item); 9013 if (err) 9014 goto err_trap_init; 9015 9016 list_add_tail(&trap_item->list, &devlink->trap_list); 9017 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 9018 9019 return 0; 9020 9021err_trap_init: 9022err_group_link: 9023 free_percpu(trap_item->stats); 9024err_stats_alloc: 9025 kfree(trap_item); 9026 return err; 9027} 9028 9029static void devlink_trap_unregister(struct devlink *devlink, 9030 const struct devlink_trap *trap) 9031{ 9032 struct devlink_trap_item *trap_item; 9033 9034 trap_item = devlink_trap_item_lookup(devlink, trap->name); 9035 if (WARN_ON_ONCE(!trap_item)) 9036 return; 9037 9038 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 9039 list_del(&trap_item->list); 9040 if (devlink->ops->trap_fini) 9041 devlink->ops->trap_fini(devlink, trap, trap_item); 9042 free_percpu(trap_item->stats); 9043 kfree(trap_item); 9044} 9045 9046static void devlink_trap_disable(struct devlink *devlink, 9047 const struct devlink_trap *trap) 9048{ 9049 struct devlink_trap_item *trap_item; 9050 9051 trap_item = devlink_trap_item_lookup(devlink, trap->name); 9052 if (WARN_ON_ONCE(!trap_item)) 9053 return; 9054 9055 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP, 9056 NULL); 9057 trap_item->action = DEVLINK_TRAP_ACTION_DROP; 9058} 9059 9060/** 9061 * devlink_traps_register - Register packet traps with devlink. 9062 * @devlink: devlink. 9063 * @traps: Packet traps. 9064 * @traps_count: Count of provided packet traps. 9065 * @priv: Driver private information. 9066 * 9067 * Return: Non-zero value on failure. 9068 */ 9069int devlink_traps_register(struct devlink *devlink, 9070 const struct devlink_trap *traps, 9071 size_t traps_count, void *priv) 9072{ 9073 int i, err; 9074 9075 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set) 9076 return -EINVAL; 9077 9078 mutex_lock(&devlink->lock); 9079 for (i = 0; i < traps_count; i++) { 9080 const struct devlink_trap *trap = &traps[i]; 9081 9082 err = devlink_trap_verify(trap); 9083 if (err) 9084 goto err_trap_verify; 9085 9086 err = devlink_trap_register(devlink, trap, priv); 9087 if (err) 9088 goto err_trap_register; 9089 } 9090 mutex_unlock(&devlink->lock); 9091 9092 return 0; 9093 9094err_trap_register: 9095err_trap_verify: 9096 for (i--; i >= 0; i--) 9097 devlink_trap_unregister(devlink, &traps[i]); 9098 mutex_unlock(&devlink->lock); 9099 return err; 9100} 9101EXPORT_SYMBOL_GPL(devlink_traps_register); 9102 9103/** 9104 * devlink_traps_unregister - Unregister packet traps from devlink. 9105 * @devlink: devlink. 9106 * @traps: Packet traps. 9107 * @traps_count: Count of provided packet traps. 9108 */ 9109void devlink_traps_unregister(struct devlink *devlink, 9110 const struct devlink_trap *traps, 9111 size_t traps_count) 9112{ 9113 int i; 9114 9115 mutex_lock(&devlink->lock); 9116 /* Make sure we do not have any packets in-flight while unregistering 9117 * traps by disabling all of them and waiting for a grace period. 9118 */ 9119 for (i = traps_count - 1; i >= 0; i--) 9120 devlink_trap_disable(devlink, &traps[i]); 9121 synchronize_rcu(); 9122 for (i = traps_count - 1; i >= 0; i--) 9123 devlink_trap_unregister(devlink, &traps[i]); 9124 mutex_unlock(&devlink->lock); 9125} 9126EXPORT_SYMBOL_GPL(devlink_traps_unregister); 9127 9128static void 9129devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats, 9130 size_t skb_len) 9131{ 9132 struct devlink_stats *stats; 9133 9134 stats = this_cpu_ptr(trap_stats); 9135 u64_stats_update_begin(&stats->syncp); 9136 stats->rx_bytes += skb_len; 9137 stats->rx_packets++; 9138 u64_stats_update_end(&stats->syncp); 9139} 9140 9141static void 9142devlink_trap_report_metadata_fill(struct net_dm_hw_metadata *hw_metadata, 9143 const struct devlink_trap_item *trap_item, 9144 struct devlink_port *in_devlink_port, 9145 const struct flow_action_cookie *fa_cookie) 9146{ 9147 struct devlink_trap_group_item *group_item = trap_item->group_item; 9148 9149 hw_metadata->trap_group_name = group_item->group->name; 9150 hw_metadata->trap_name = trap_item->trap->name; 9151 hw_metadata->fa_cookie = fa_cookie; 9152 9153 spin_lock(&in_devlink_port->type_lock); 9154 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH) 9155 hw_metadata->input_dev = in_devlink_port->type_dev; 9156 spin_unlock(&in_devlink_port->type_lock); 9157} 9158 9159/** 9160 * devlink_trap_report - Report trapped packet to drop monitor. 9161 * @devlink: devlink. 9162 * @skb: Trapped packet. 9163 * @trap_ctx: Trap context. 9164 * @in_devlink_port: Input devlink port. 9165 * @fa_cookie: Flow action cookie. Could be NULL. 9166 */ 9167void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb, 9168 void *trap_ctx, struct devlink_port *in_devlink_port, 9169 const struct flow_action_cookie *fa_cookie) 9170 9171{ 9172 struct devlink_trap_item *trap_item = trap_ctx; 9173 struct net_dm_hw_metadata hw_metadata = {}; 9174 9175 devlink_trap_stats_update(trap_item->stats, skb->len); 9176 devlink_trap_stats_update(trap_item->group_item->stats, skb->len); 9177 9178 /* Control packets were not dropped by the device or encountered an 9179 * exception during forwarding and therefore should not be reported to 9180 * the kernel's drop monitor. 9181 */ 9182 if (trap_item->trap->type == DEVLINK_TRAP_TYPE_CONTROL) 9183 return; 9184 9185 devlink_trap_report_metadata_fill(&hw_metadata, trap_item, 9186 in_devlink_port, fa_cookie); 9187 net_dm_hw_report(skb, &hw_metadata); 9188} 9189EXPORT_SYMBOL_GPL(devlink_trap_report); 9190 9191/** 9192 * devlink_trap_ctx_priv - Trap context to driver private information. 9193 * @trap_ctx: Trap context. 9194 * 9195 * Return: Driver private information passed during registration. 9196 */ 9197void *devlink_trap_ctx_priv(void *trap_ctx) 9198{ 9199 struct devlink_trap_item *trap_item = trap_ctx; 9200 9201 return trap_item->priv; 9202} 9203EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv); 9204 9205static int 9206devlink_trap_group_item_policer_link(struct devlink *devlink, 9207 struct devlink_trap_group_item *group_item) 9208{ 9209 u32 policer_id = group_item->group->init_policer_id; 9210 struct devlink_trap_policer_item *policer_item; 9211 9212 if (policer_id == 0) 9213 return 0; 9214 9215 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 9216 if (WARN_ON_ONCE(!policer_item)) 9217 return -EINVAL; 9218 9219 group_item->policer_item = policer_item; 9220 9221 return 0; 9222} 9223 9224static int 9225devlink_trap_group_register(struct devlink *devlink, 9226 const struct devlink_trap_group *group) 9227{ 9228 struct devlink_trap_group_item *group_item; 9229 int err; 9230 9231 if (devlink_trap_group_item_lookup(devlink, group->name)) 9232 return -EEXIST; 9233 9234 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL); 9235 if (!group_item) 9236 return -ENOMEM; 9237 9238 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 9239 if (!group_item->stats) { 9240 err = -ENOMEM; 9241 goto err_stats_alloc; 9242 } 9243 9244 group_item->group = group; 9245 9246 err = devlink_trap_group_item_policer_link(devlink, group_item); 9247 if (err) 9248 goto err_policer_link; 9249 9250 if (devlink->ops->trap_group_init) { 9251 err = devlink->ops->trap_group_init(devlink, group); 9252 if (err) 9253 goto err_group_init; 9254 } 9255 9256 list_add_tail(&group_item->list, &devlink->trap_group_list); 9257 devlink_trap_group_notify(devlink, group_item, 9258 DEVLINK_CMD_TRAP_GROUP_NEW); 9259 9260 return 0; 9261 9262err_group_init: 9263err_policer_link: 9264 free_percpu(group_item->stats); 9265err_stats_alloc: 9266 kfree(group_item); 9267 return err; 9268} 9269 9270static void 9271devlink_trap_group_unregister(struct devlink *devlink, 9272 const struct devlink_trap_group *group) 9273{ 9274 struct devlink_trap_group_item *group_item; 9275 9276 group_item = devlink_trap_group_item_lookup(devlink, group->name); 9277 if (WARN_ON_ONCE(!group_item)) 9278 return; 9279 9280 devlink_trap_group_notify(devlink, group_item, 9281 DEVLINK_CMD_TRAP_GROUP_DEL); 9282 list_del(&group_item->list); 9283 free_percpu(group_item->stats); 9284 kfree(group_item); 9285} 9286 9287/** 9288 * devlink_trap_groups_register - Register packet trap groups with devlink. 9289 * @devlink: devlink. 9290 * @groups: Packet trap groups. 9291 * @groups_count: Count of provided packet trap groups. 9292 * 9293 * Return: Non-zero value on failure. 9294 */ 9295int devlink_trap_groups_register(struct devlink *devlink, 9296 const struct devlink_trap_group *groups, 9297 size_t groups_count) 9298{ 9299 int i, err; 9300 9301 mutex_lock(&devlink->lock); 9302 for (i = 0; i < groups_count; i++) { 9303 const struct devlink_trap_group *group = &groups[i]; 9304 9305 err = devlink_trap_group_verify(group); 9306 if (err) 9307 goto err_trap_group_verify; 9308 9309 err = devlink_trap_group_register(devlink, group); 9310 if (err) 9311 goto err_trap_group_register; 9312 } 9313 mutex_unlock(&devlink->lock); 9314 9315 return 0; 9316 9317err_trap_group_register: 9318err_trap_group_verify: 9319 for (i--; i >= 0; i--) 9320 devlink_trap_group_unregister(devlink, &groups[i]); 9321 mutex_unlock(&devlink->lock); 9322 return err; 9323} 9324EXPORT_SYMBOL_GPL(devlink_trap_groups_register); 9325 9326/** 9327 * devlink_trap_groups_unregister - Unregister packet trap groups from devlink. 9328 * @devlink: devlink. 9329 * @groups: Packet trap groups. 9330 * @groups_count: Count of provided packet trap groups. 9331 */ 9332void devlink_trap_groups_unregister(struct devlink *devlink, 9333 const struct devlink_trap_group *groups, 9334 size_t groups_count) 9335{ 9336 int i; 9337 9338 mutex_lock(&devlink->lock); 9339 for (i = groups_count - 1; i >= 0; i--) 9340 devlink_trap_group_unregister(devlink, &groups[i]); 9341 mutex_unlock(&devlink->lock); 9342} 9343EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister); 9344 9345static void 9346devlink_trap_policer_notify(struct devlink *devlink, 9347 const struct devlink_trap_policer_item *policer_item, 9348 enum devlink_command cmd) 9349{ 9350 struct sk_buff *msg; 9351 int err; 9352 9353 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW && 9354 cmd != DEVLINK_CMD_TRAP_POLICER_DEL); 9355 9356 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 9357 if (!msg) 9358 return; 9359 9360 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0, 9361 0, 0); 9362 if (err) { 9363 nlmsg_free(msg); 9364 return; 9365 } 9366 9367 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 9368 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 9369} 9370 9371static int 9372devlink_trap_policer_register(struct devlink *devlink, 9373 const struct devlink_trap_policer *policer) 9374{ 9375 struct devlink_trap_policer_item *policer_item; 9376 int err; 9377 9378 if (devlink_trap_policer_item_lookup(devlink, policer->id)) 9379 return -EEXIST; 9380 9381 policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL); 9382 if (!policer_item) 9383 return -ENOMEM; 9384 9385 policer_item->policer = policer; 9386 policer_item->rate = policer->init_rate; 9387 policer_item->burst = policer->init_burst; 9388 9389 if (devlink->ops->trap_policer_init) { 9390 err = devlink->ops->trap_policer_init(devlink, policer); 9391 if (err) 9392 goto err_policer_init; 9393 } 9394 9395 list_add_tail(&policer_item->list, &devlink->trap_policer_list); 9396 devlink_trap_policer_notify(devlink, policer_item, 9397 DEVLINK_CMD_TRAP_POLICER_NEW); 9398 9399 return 0; 9400 9401err_policer_init: 9402 kfree(policer_item); 9403 return err; 9404} 9405 9406static void 9407devlink_trap_policer_unregister(struct devlink *devlink, 9408 const struct devlink_trap_policer *policer) 9409{ 9410 struct devlink_trap_policer_item *policer_item; 9411 9412 policer_item = devlink_trap_policer_item_lookup(devlink, policer->id); 9413 if (WARN_ON_ONCE(!policer_item)) 9414 return; 9415 9416 devlink_trap_policer_notify(devlink, policer_item, 9417 DEVLINK_CMD_TRAP_POLICER_DEL); 9418 list_del(&policer_item->list); 9419 if (devlink->ops->trap_policer_fini) 9420 devlink->ops->trap_policer_fini(devlink, policer); 9421 kfree(policer_item); 9422} 9423 9424/** 9425 * devlink_trap_policers_register - Register packet trap policers with devlink. 9426 * @devlink: devlink. 9427 * @policers: Packet trap policers. 9428 * @policers_count: Count of provided packet trap policers. 9429 * 9430 * Return: Non-zero value on failure. 9431 */ 9432int 9433devlink_trap_policers_register(struct devlink *devlink, 9434 const struct devlink_trap_policer *policers, 9435 size_t policers_count) 9436{ 9437 int i, err; 9438 9439 mutex_lock(&devlink->lock); 9440 for (i = 0; i < policers_count; i++) { 9441 const struct devlink_trap_policer *policer = &policers[i]; 9442 9443 if (WARN_ON(policer->id == 0 || 9444 policer->max_rate < policer->min_rate || 9445 policer->max_burst < policer->min_burst)) { 9446 err = -EINVAL; 9447 goto err_trap_policer_verify; 9448 } 9449 9450 err = devlink_trap_policer_register(devlink, policer); 9451 if (err) 9452 goto err_trap_policer_register; 9453 } 9454 mutex_unlock(&devlink->lock); 9455 9456 return 0; 9457 9458err_trap_policer_register: 9459err_trap_policer_verify: 9460 for (i--; i >= 0; i--) 9461 devlink_trap_policer_unregister(devlink, &policers[i]); 9462 mutex_unlock(&devlink->lock); 9463 return err; 9464} 9465EXPORT_SYMBOL_GPL(devlink_trap_policers_register); 9466 9467/** 9468 * devlink_trap_policers_unregister - Unregister packet trap policers from devlink. 9469 * @devlink: devlink. 9470 * @policers: Packet trap policers. 9471 * @policers_count: Count of provided packet trap policers. 9472 */ 9473void 9474devlink_trap_policers_unregister(struct devlink *devlink, 9475 const struct devlink_trap_policer *policers, 9476 size_t policers_count) 9477{ 9478 int i; 9479 9480 mutex_lock(&devlink->lock); 9481 for (i = policers_count - 1; i >= 0; i--) 9482 devlink_trap_policer_unregister(devlink, &policers[i]); 9483 mutex_unlock(&devlink->lock); 9484} 9485EXPORT_SYMBOL_GPL(devlink_trap_policers_unregister); 9486 9487static void __devlink_compat_running_version(struct devlink *devlink, 9488 char *buf, size_t len) 9489{ 9490 const struct nlattr *nlattr; 9491 struct devlink_info_req req; 9492 struct sk_buff *msg; 9493 int rem, err; 9494 9495 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 9496 if (!msg) 9497 return; 9498 9499 req.msg = msg; 9500 err = devlink->ops->info_get(devlink, &req, NULL); 9501 if (err) 9502 goto free_msg; 9503 9504 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) { 9505 const struct nlattr *kv; 9506 int rem_kv; 9507 9508 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING) 9509 continue; 9510 9511 nla_for_each_nested(kv, nlattr, rem_kv) { 9512 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE) 9513 continue; 9514 9515 strlcat(buf, nla_data(kv), len); 9516 strlcat(buf, " ", len); 9517 } 9518 } 9519free_msg: 9520 nlmsg_free(msg); 9521} 9522 9523void devlink_compat_running_version(struct net_device *dev, 9524 char *buf, size_t len) 9525{ 9526 struct devlink *devlink; 9527 9528 dev_hold(dev); 9529 rtnl_unlock(); 9530 9531 devlink = netdev_to_devlink(dev); 9532 if (!devlink || !devlink->ops->info_get) 9533 goto out; 9534 9535 mutex_lock(&devlink->lock); 9536 __devlink_compat_running_version(devlink, buf, len); 9537 mutex_unlock(&devlink->lock); 9538 9539out: 9540 rtnl_lock(); 9541 dev_put(dev); 9542} 9543 9544int devlink_compat_flash_update(struct net_device *dev, const char *file_name) 9545{ 9546 struct devlink *devlink; 9547 int ret; 9548 9549 dev_hold(dev); 9550 rtnl_unlock(); 9551 9552 devlink = netdev_to_devlink(dev); 9553 if (!devlink || !devlink->ops->flash_update) { 9554 ret = -EOPNOTSUPP; 9555 goto out; 9556 } 9557 9558 mutex_lock(&devlink->lock); 9559 ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL); 9560 mutex_unlock(&devlink->lock); 9561 9562out: 9563 rtnl_lock(); 9564 dev_put(dev); 9565 9566 return ret; 9567} 9568 9569int devlink_compat_phys_port_name_get(struct net_device *dev, 9570 char *name, size_t len) 9571{ 9572 struct devlink_port *devlink_port; 9573 9574 /* RTNL mutex is held here which ensures that devlink_port 9575 * instance cannot disappear in the middle. No need to take 9576 * any devlink lock as only permanent values are accessed. 9577 */ 9578 ASSERT_RTNL(); 9579 9580 devlink_port = netdev_to_devlink_port(dev); 9581 if (!devlink_port) 9582 return -EOPNOTSUPP; 9583 9584 return __devlink_port_phys_port_name_get(devlink_port, name, len); 9585} 9586 9587int devlink_compat_switch_id_get(struct net_device *dev, 9588 struct netdev_phys_item_id *ppid) 9589{ 9590 struct devlink_port *devlink_port; 9591 9592 /* Caller must hold RTNL mutex or reference to dev, which ensures that 9593 * devlink_port instance cannot disappear in the middle. No need to take 9594 * any devlink lock as only permanent values are accessed. 9595 */ 9596 devlink_port = netdev_to_devlink_port(dev); 9597 if (!devlink_port || !devlink_port->switch_port) 9598 return -EOPNOTSUPP; 9599 9600 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid)); 9601 9602 return 0; 9603} 9604 9605static void __net_exit devlink_pernet_pre_exit(struct net *net) 9606{ 9607 struct devlink *devlink; 9608 int err; 9609 9610 /* In case network namespace is getting destroyed, reload 9611 * all devlink instances from this namespace into init_net. 9612 */ 9613 mutex_lock(&devlink_mutex); 9614 list_for_each_entry(devlink, &devlink_list, list) { 9615 if (net_eq(devlink_net(devlink), net)) { 9616 if (WARN_ON(!devlink_reload_supported(devlink))) 9617 continue; 9618 err = devlink_reload(devlink, &init_net, NULL); 9619 if (err && err != -EOPNOTSUPP) 9620 pr_warn("Failed to reload devlink instance into init_net\n"); 9621 } 9622 } 9623 mutex_unlock(&devlink_mutex); 9624} 9625 9626static struct pernet_operations devlink_pernet_ops __net_initdata = { 9627 .pre_exit = devlink_pernet_pre_exit, 9628}; 9629 9630static int __init devlink_init(void) 9631{ 9632 int err; 9633 9634 err = genl_register_family(&devlink_nl_family); 9635 if (err) 9636 goto out; 9637 err = register_pernet_subsys(&devlink_pernet_ops); 9638 9639out: 9640 WARN_ON(err); 9641 return err; 9642} 9643 9644subsys_initcall(devlink_init);