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