at v4.18 90 kB view raw
1/* 2 * net/core/devlink.c - Network physical/parent device Netlink interface 3 * 4 * Heavily inspired by net/wireless/ 5 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 6 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/types.h> 17#include <linux/slab.h> 18#include <linux/gfp.h> 19#include <linux/device.h> 20#include <linux/list.h> 21#include <linux/netdevice.h> 22#include <rdma/ib_verbs.h> 23#include <net/netlink.h> 24#include <net/genetlink.h> 25#include <net/rtnetlink.h> 26#include <net/net_namespace.h> 27#include <net/sock.h> 28#include <net/devlink.h> 29#define CREATE_TRACE_POINTS 30#include <trace/events/devlink.h> 31 32static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = { 33 { 34 .name = "destination mac", 35 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, 36 .bitwidth = 48, 37 }, 38}; 39 40struct devlink_dpipe_header devlink_dpipe_header_ethernet = { 41 .name = "ethernet", 42 .id = DEVLINK_DPIPE_HEADER_ETHERNET, 43 .fields = devlink_dpipe_fields_ethernet, 44 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet), 45 .global = true, 46}; 47EXPORT_SYMBOL(devlink_dpipe_header_ethernet); 48 49static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = { 50 { 51 .name = "destination ip", 52 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP, 53 .bitwidth = 32, 54 }, 55}; 56 57struct devlink_dpipe_header devlink_dpipe_header_ipv4 = { 58 .name = "ipv4", 59 .id = DEVLINK_DPIPE_HEADER_IPV4, 60 .fields = devlink_dpipe_fields_ipv4, 61 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4), 62 .global = true, 63}; 64EXPORT_SYMBOL(devlink_dpipe_header_ipv4); 65 66static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = { 67 { 68 .name = "destination ip", 69 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP, 70 .bitwidth = 128, 71 }, 72}; 73 74struct devlink_dpipe_header devlink_dpipe_header_ipv6 = { 75 .name = "ipv6", 76 .id = DEVLINK_DPIPE_HEADER_IPV6, 77 .fields = devlink_dpipe_fields_ipv6, 78 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6), 79 .global = true, 80}; 81EXPORT_SYMBOL(devlink_dpipe_header_ipv6); 82 83EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg); 84 85static LIST_HEAD(devlink_list); 86 87/* devlink_mutex 88 * 89 * An overall lock guarding every operation coming from userspace. 90 * It also guards devlink devices list and it is taken when 91 * driver registers/unregisters it. 92 */ 93static DEFINE_MUTEX(devlink_mutex); 94 95static struct net *devlink_net(const struct devlink *devlink) 96{ 97 return read_pnet(&devlink->_net); 98} 99 100static void devlink_net_set(struct devlink *devlink, struct net *net) 101{ 102 write_pnet(&devlink->_net, net); 103} 104 105static struct devlink *devlink_get_from_attrs(struct net *net, 106 struct nlattr **attrs) 107{ 108 struct devlink *devlink; 109 char *busname; 110 char *devname; 111 112 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME]) 113 return ERR_PTR(-EINVAL); 114 115 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); 116 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); 117 118 list_for_each_entry(devlink, &devlink_list, list) { 119 if (strcmp(devlink->dev->bus->name, busname) == 0 && 120 strcmp(dev_name(devlink->dev), devname) == 0 && 121 net_eq(devlink_net(devlink), net)) 122 return devlink; 123 } 124 125 return ERR_PTR(-ENODEV); 126} 127 128static struct devlink *devlink_get_from_info(struct genl_info *info) 129{ 130 return devlink_get_from_attrs(genl_info_net(info), info->attrs); 131} 132 133static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 134 int port_index) 135{ 136 struct devlink_port *devlink_port; 137 138 list_for_each_entry(devlink_port, &devlink->port_list, list) { 139 if (devlink_port->index == port_index) 140 return devlink_port; 141 } 142 return NULL; 143} 144 145static bool devlink_port_index_exists(struct devlink *devlink, int port_index) 146{ 147 return devlink_port_get_by_index(devlink, port_index); 148} 149 150static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 151 struct nlattr **attrs) 152{ 153 if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 154 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 155 struct devlink_port *devlink_port; 156 157 devlink_port = devlink_port_get_by_index(devlink, port_index); 158 if (!devlink_port) 159 return ERR_PTR(-ENODEV); 160 return devlink_port; 161 } 162 return ERR_PTR(-EINVAL); 163} 164 165static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 166 struct genl_info *info) 167{ 168 return devlink_port_get_from_attrs(devlink, info->attrs); 169} 170 171struct devlink_sb { 172 struct list_head list; 173 unsigned int index; 174 u32 size; 175 u16 ingress_pools_count; 176 u16 egress_pools_count; 177 u16 ingress_tc_count; 178 u16 egress_tc_count; 179}; 180 181static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 182{ 183 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 184} 185 186static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 187 unsigned int sb_index) 188{ 189 struct devlink_sb *devlink_sb; 190 191 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 192 if (devlink_sb->index == sb_index) 193 return devlink_sb; 194 } 195 return NULL; 196} 197 198static bool devlink_sb_index_exists(struct devlink *devlink, 199 unsigned int sb_index) 200{ 201 return devlink_sb_get_by_index(devlink, sb_index); 202} 203 204static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 205 struct nlattr **attrs) 206{ 207 if (attrs[DEVLINK_ATTR_SB_INDEX]) { 208 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 209 struct devlink_sb *devlink_sb; 210 211 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 212 if (!devlink_sb) 213 return ERR_PTR(-ENODEV); 214 return devlink_sb; 215 } 216 return ERR_PTR(-EINVAL); 217} 218 219static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 220 struct genl_info *info) 221{ 222 return devlink_sb_get_from_attrs(devlink, info->attrs); 223} 224 225static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 226 struct nlattr **attrs, 227 u16 *p_pool_index) 228{ 229 u16 val; 230 231 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 232 return -EINVAL; 233 234 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 235 if (val >= devlink_sb_pool_count(devlink_sb)) 236 return -EINVAL; 237 *p_pool_index = val; 238 return 0; 239} 240 241static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 242 struct genl_info *info, 243 u16 *p_pool_index) 244{ 245 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 246 p_pool_index); 247} 248 249static int 250devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 251 enum devlink_sb_pool_type *p_pool_type) 252{ 253 u8 val; 254 255 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 256 return -EINVAL; 257 258 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 259 if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 260 val != DEVLINK_SB_POOL_TYPE_EGRESS) 261 return -EINVAL; 262 *p_pool_type = val; 263 return 0; 264} 265 266static int 267devlink_sb_pool_type_get_from_info(struct genl_info *info, 268 enum devlink_sb_pool_type *p_pool_type) 269{ 270 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 271} 272 273static int 274devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 275 enum devlink_sb_threshold_type *p_th_type) 276{ 277 u8 val; 278 279 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 280 return -EINVAL; 281 282 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 283 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 284 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 285 return -EINVAL; 286 *p_th_type = val; 287 return 0; 288} 289 290static int 291devlink_sb_th_type_get_from_info(struct genl_info *info, 292 enum devlink_sb_threshold_type *p_th_type) 293{ 294 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 295} 296 297static int 298devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 299 struct nlattr **attrs, 300 enum devlink_sb_pool_type pool_type, 301 u16 *p_tc_index) 302{ 303 u16 val; 304 305 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 306 return -EINVAL; 307 308 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 309 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 310 val >= devlink_sb->ingress_tc_count) 311 return -EINVAL; 312 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 313 val >= devlink_sb->egress_tc_count) 314 return -EINVAL; 315 *p_tc_index = val; 316 return 0; 317} 318 319static int 320devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 321 struct genl_info *info, 322 enum devlink_sb_pool_type pool_type, 323 u16 *p_tc_index) 324{ 325 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 326 pool_type, p_tc_index); 327} 328 329#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) 330#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) 331#define DEVLINK_NL_FLAG_NEED_SB BIT(2) 332 333/* The per devlink instance lock is taken by default in the pre-doit 334 * operation, yet several commands do not require this. The global 335 * devlink lock is taken and protects from disruption by user-calls. 336 */ 337#define DEVLINK_NL_FLAG_NO_LOCK BIT(3) 338 339static int devlink_nl_pre_doit(const struct genl_ops *ops, 340 struct sk_buff *skb, struct genl_info *info) 341{ 342 struct devlink *devlink; 343 int err; 344 345 mutex_lock(&devlink_mutex); 346 devlink = devlink_get_from_info(info); 347 if (IS_ERR(devlink)) { 348 mutex_unlock(&devlink_mutex); 349 return PTR_ERR(devlink); 350 } 351 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 352 mutex_lock(&devlink->lock); 353 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) { 354 info->user_ptr[0] = devlink; 355 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { 356 struct devlink_port *devlink_port; 357 358 devlink_port = devlink_port_get_from_info(devlink, info); 359 if (IS_ERR(devlink_port)) { 360 err = PTR_ERR(devlink_port); 361 goto unlock; 362 } 363 info->user_ptr[0] = devlink_port; 364 } 365 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { 366 struct devlink_sb *devlink_sb; 367 368 devlink_sb = devlink_sb_get_from_info(devlink, info); 369 if (IS_ERR(devlink_sb)) { 370 err = PTR_ERR(devlink_sb); 371 goto unlock; 372 } 373 info->user_ptr[1] = devlink_sb; 374 } 375 return 0; 376 377unlock: 378 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 379 mutex_unlock(&devlink->lock); 380 mutex_unlock(&devlink_mutex); 381 return err; 382} 383 384static void devlink_nl_post_doit(const struct genl_ops *ops, 385 struct sk_buff *skb, struct genl_info *info) 386{ 387 struct devlink *devlink; 388 389 devlink = devlink_get_from_info(info); 390 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 391 mutex_unlock(&devlink->lock); 392 mutex_unlock(&devlink_mutex); 393} 394 395static struct genl_family devlink_nl_family; 396 397enum devlink_multicast_groups { 398 DEVLINK_MCGRP_CONFIG, 399}; 400 401static const struct genl_multicast_group devlink_nl_mcgrps[] = { 402 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, 403}; 404 405static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink) 406{ 407 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name)) 408 return -EMSGSIZE; 409 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 410 return -EMSGSIZE; 411 return 0; 412} 413 414static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, 415 enum devlink_command cmd, u32 portid, 416 u32 seq, int flags) 417{ 418 void *hdr; 419 420 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 421 if (!hdr) 422 return -EMSGSIZE; 423 424 if (devlink_nl_put_handle(msg, devlink)) 425 goto nla_put_failure; 426 427 genlmsg_end(msg, hdr); 428 return 0; 429 430nla_put_failure: 431 genlmsg_cancel(msg, hdr); 432 return -EMSGSIZE; 433} 434 435static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 436{ 437 struct sk_buff *msg; 438 int err; 439 440 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL); 441 442 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 443 if (!msg) 444 return; 445 446 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0); 447 if (err) { 448 nlmsg_free(msg); 449 return; 450 } 451 452 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 453 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 454} 455 456static int devlink_nl_port_attrs_put(struct sk_buff *msg, 457 struct devlink_port *devlink_port) 458{ 459 struct devlink_port_attrs *attrs = &devlink_port->attrs; 460 461 if (!attrs->set) 462 return 0; 463 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 464 return -EMSGSIZE; 465 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number)) 466 return -EMSGSIZE; 467 if (!attrs->split) 468 return 0; 469 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number)) 470 return -EMSGSIZE; 471 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 472 attrs->split_subport_number)) 473 return -EMSGSIZE; 474 return 0; 475} 476 477static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, 478 struct devlink_port *devlink_port, 479 enum devlink_command cmd, u32 portid, 480 u32 seq, int flags) 481{ 482 void *hdr; 483 484 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 485 if (!hdr) 486 return -EMSGSIZE; 487 488 if (devlink_nl_put_handle(msg, devlink)) 489 goto nla_put_failure; 490 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 491 goto nla_put_failure; 492 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 493 goto nla_put_failure; 494 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 495 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 496 devlink_port->desired_type)) 497 goto nla_put_failure; 498 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 499 struct net_device *netdev = devlink_port->type_dev; 500 501 if (netdev && 502 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 503 netdev->ifindex) || 504 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 505 netdev->name))) 506 goto nla_put_failure; 507 } 508 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 509 struct ib_device *ibdev = devlink_port->type_dev; 510 511 if (ibdev && 512 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 513 ibdev->name)) 514 goto nla_put_failure; 515 } 516 if (devlink_nl_port_attrs_put(msg, devlink_port)) 517 goto nla_put_failure; 518 519 genlmsg_end(msg, hdr); 520 return 0; 521 522nla_put_failure: 523 genlmsg_cancel(msg, hdr); 524 return -EMSGSIZE; 525} 526 527static void devlink_port_notify(struct devlink_port *devlink_port, 528 enum devlink_command cmd) 529{ 530 struct devlink *devlink = devlink_port->devlink; 531 struct sk_buff *msg; 532 int err; 533 534 if (!devlink_port->registered) 535 return; 536 537 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 538 539 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 540 if (!msg) 541 return; 542 543 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0); 544 if (err) { 545 nlmsg_free(msg); 546 return; 547 } 548 549 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 550 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 551} 552 553static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info) 554{ 555 struct devlink *devlink = info->user_ptr[0]; 556 struct sk_buff *msg; 557 int err; 558 559 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 560 if (!msg) 561 return -ENOMEM; 562 563 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 564 info->snd_portid, info->snd_seq, 0); 565 if (err) { 566 nlmsg_free(msg); 567 return err; 568 } 569 570 return genlmsg_reply(msg, info); 571} 572 573static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, 574 struct netlink_callback *cb) 575{ 576 struct devlink *devlink; 577 int start = cb->args[0]; 578 int idx = 0; 579 int err; 580 581 mutex_lock(&devlink_mutex); 582 list_for_each_entry(devlink, &devlink_list, list) { 583 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 584 continue; 585 if (idx < start) { 586 idx++; 587 continue; 588 } 589 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 590 NETLINK_CB(cb->skb).portid, 591 cb->nlh->nlmsg_seq, NLM_F_MULTI); 592 if (err) 593 goto out; 594 idx++; 595 } 596out: 597 mutex_unlock(&devlink_mutex); 598 599 cb->args[0] = idx; 600 return msg->len; 601} 602 603static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, 604 struct genl_info *info) 605{ 606 struct devlink_port *devlink_port = info->user_ptr[0]; 607 struct devlink *devlink = devlink_port->devlink; 608 struct sk_buff *msg; 609 int err; 610 611 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 612 if (!msg) 613 return -ENOMEM; 614 615 err = devlink_nl_port_fill(msg, devlink, devlink_port, 616 DEVLINK_CMD_PORT_NEW, 617 info->snd_portid, info->snd_seq, 0); 618 if (err) { 619 nlmsg_free(msg); 620 return err; 621 } 622 623 return genlmsg_reply(msg, info); 624} 625 626static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, 627 struct netlink_callback *cb) 628{ 629 struct devlink *devlink; 630 struct devlink_port *devlink_port; 631 int start = cb->args[0]; 632 int idx = 0; 633 int err; 634 635 mutex_lock(&devlink_mutex); 636 list_for_each_entry(devlink, &devlink_list, list) { 637 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 638 continue; 639 mutex_lock(&devlink->lock); 640 list_for_each_entry(devlink_port, &devlink->port_list, list) { 641 if (idx < start) { 642 idx++; 643 continue; 644 } 645 err = devlink_nl_port_fill(msg, devlink, devlink_port, 646 DEVLINK_CMD_NEW, 647 NETLINK_CB(cb->skb).portid, 648 cb->nlh->nlmsg_seq, 649 NLM_F_MULTI); 650 if (err) { 651 mutex_unlock(&devlink->lock); 652 goto out; 653 } 654 idx++; 655 } 656 mutex_unlock(&devlink->lock); 657 } 658out: 659 mutex_unlock(&devlink_mutex); 660 661 cb->args[0] = idx; 662 return msg->len; 663} 664 665static int devlink_port_type_set(struct devlink *devlink, 666 struct devlink_port *devlink_port, 667 enum devlink_port_type port_type) 668 669{ 670 int err; 671 672 if (devlink->ops && devlink->ops->port_type_set) { 673 if (port_type == DEVLINK_PORT_TYPE_NOTSET) 674 return -EINVAL; 675 if (port_type == devlink_port->type) 676 return 0; 677 err = devlink->ops->port_type_set(devlink_port, port_type); 678 if (err) 679 return err; 680 devlink_port->desired_type = port_type; 681 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 682 return 0; 683 } 684 return -EOPNOTSUPP; 685} 686 687static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 688 struct genl_info *info) 689{ 690 struct devlink_port *devlink_port = info->user_ptr[0]; 691 struct devlink *devlink = devlink_port->devlink; 692 int err; 693 694 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 695 enum devlink_port_type port_type; 696 697 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 698 err = devlink_port_type_set(devlink, devlink_port, port_type); 699 if (err) 700 return err; 701 } 702 return 0; 703} 704 705static int devlink_port_split(struct devlink *devlink, u32 port_index, 706 u32 count, struct netlink_ext_ack *extack) 707 708{ 709 if (devlink->ops && devlink->ops->port_split) 710 return devlink->ops->port_split(devlink, port_index, count, 711 extack); 712 return -EOPNOTSUPP; 713} 714 715static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 716 struct genl_info *info) 717{ 718 struct devlink *devlink = info->user_ptr[0]; 719 u32 port_index; 720 u32 count; 721 722 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] || 723 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]) 724 return -EINVAL; 725 726 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 727 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 728 return devlink_port_split(devlink, port_index, count, info->extack); 729} 730 731static int devlink_port_unsplit(struct devlink *devlink, u32 port_index, 732 struct netlink_ext_ack *extack) 733 734{ 735 if (devlink->ops && devlink->ops->port_unsplit) 736 return devlink->ops->port_unsplit(devlink, port_index, extack); 737 return -EOPNOTSUPP; 738} 739 740static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 741 struct genl_info *info) 742{ 743 struct devlink *devlink = info->user_ptr[0]; 744 u32 port_index; 745 746 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) 747 return -EINVAL; 748 749 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 750 return devlink_port_unsplit(devlink, port_index, info->extack); 751} 752 753static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 754 struct devlink_sb *devlink_sb, 755 enum devlink_command cmd, u32 portid, 756 u32 seq, int flags) 757{ 758 void *hdr; 759 760 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 761 if (!hdr) 762 return -EMSGSIZE; 763 764 if (devlink_nl_put_handle(msg, devlink)) 765 goto nla_put_failure; 766 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 767 goto nla_put_failure; 768 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 769 goto nla_put_failure; 770 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 771 devlink_sb->ingress_pools_count)) 772 goto nla_put_failure; 773 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 774 devlink_sb->egress_pools_count)) 775 goto nla_put_failure; 776 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 777 devlink_sb->ingress_tc_count)) 778 goto nla_put_failure; 779 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 780 devlink_sb->egress_tc_count)) 781 goto nla_put_failure; 782 783 genlmsg_end(msg, hdr); 784 return 0; 785 786nla_put_failure: 787 genlmsg_cancel(msg, hdr); 788 return -EMSGSIZE; 789} 790 791static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, 792 struct genl_info *info) 793{ 794 struct devlink *devlink = info->user_ptr[0]; 795 struct devlink_sb *devlink_sb = info->user_ptr[1]; 796 struct sk_buff *msg; 797 int err; 798 799 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 800 if (!msg) 801 return -ENOMEM; 802 803 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 804 DEVLINK_CMD_SB_NEW, 805 info->snd_portid, info->snd_seq, 0); 806 if (err) { 807 nlmsg_free(msg); 808 return err; 809 } 810 811 return genlmsg_reply(msg, info); 812} 813 814static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, 815 struct netlink_callback *cb) 816{ 817 struct devlink *devlink; 818 struct devlink_sb *devlink_sb; 819 int start = cb->args[0]; 820 int idx = 0; 821 int err; 822 823 mutex_lock(&devlink_mutex); 824 list_for_each_entry(devlink, &devlink_list, list) { 825 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 826 continue; 827 mutex_lock(&devlink->lock); 828 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 829 if (idx < start) { 830 idx++; 831 continue; 832 } 833 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 834 DEVLINK_CMD_SB_NEW, 835 NETLINK_CB(cb->skb).portid, 836 cb->nlh->nlmsg_seq, 837 NLM_F_MULTI); 838 if (err) { 839 mutex_unlock(&devlink->lock); 840 goto out; 841 } 842 idx++; 843 } 844 mutex_unlock(&devlink->lock); 845 } 846out: 847 mutex_unlock(&devlink_mutex); 848 849 cb->args[0] = idx; 850 return msg->len; 851} 852 853static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 854 struct devlink_sb *devlink_sb, 855 u16 pool_index, enum devlink_command cmd, 856 u32 portid, u32 seq, int flags) 857{ 858 struct devlink_sb_pool_info pool_info; 859 void *hdr; 860 int err; 861 862 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 863 pool_index, &pool_info); 864 if (err) 865 return err; 866 867 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 868 if (!hdr) 869 return -EMSGSIZE; 870 871 if (devlink_nl_put_handle(msg, devlink)) 872 goto nla_put_failure; 873 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 874 goto nla_put_failure; 875 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 876 goto nla_put_failure; 877 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 878 goto nla_put_failure; 879 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 880 goto nla_put_failure; 881 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 882 pool_info.threshold_type)) 883 goto nla_put_failure; 884 885 genlmsg_end(msg, hdr); 886 return 0; 887 888nla_put_failure: 889 genlmsg_cancel(msg, hdr); 890 return -EMSGSIZE; 891} 892 893static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, 894 struct genl_info *info) 895{ 896 struct devlink *devlink = info->user_ptr[0]; 897 struct devlink_sb *devlink_sb = info->user_ptr[1]; 898 struct sk_buff *msg; 899 u16 pool_index; 900 int err; 901 902 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 903 &pool_index); 904 if (err) 905 return err; 906 907 if (!devlink->ops || !devlink->ops->sb_pool_get) 908 return -EOPNOTSUPP; 909 910 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 911 if (!msg) 912 return -ENOMEM; 913 914 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 915 DEVLINK_CMD_SB_POOL_NEW, 916 info->snd_portid, info->snd_seq, 0); 917 if (err) { 918 nlmsg_free(msg); 919 return err; 920 } 921 922 return genlmsg_reply(msg, info); 923} 924 925static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 926 struct devlink *devlink, 927 struct devlink_sb *devlink_sb, 928 u32 portid, u32 seq) 929{ 930 u16 pool_count = devlink_sb_pool_count(devlink_sb); 931 u16 pool_index; 932 int err; 933 934 for (pool_index = 0; pool_index < pool_count; pool_index++) { 935 if (*p_idx < start) { 936 (*p_idx)++; 937 continue; 938 } 939 err = devlink_nl_sb_pool_fill(msg, devlink, 940 devlink_sb, 941 pool_index, 942 DEVLINK_CMD_SB_POOL_NEW, 943 portid, seq, NLM_F_MULTI); 944 if (err) 945 return err; 946 (*p_idx)++; 947 } 948 return 0; 949} 950 951static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, 952 struct netlink_callback *cb) 953{ 954 struct devlink *devlink; 955 struct devlink_sb *devlink_sb; 956 int start = cb->args[0]; 957 int idx = 0; 958 int err; 959 960 mutex_lock(&devlink_mutex); 961 list_for_each_entry(devlink, &devlink_list, list) { 962 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 963 !devlink->ops || !devlink->ops->sb_pool_get) 964 continue; 965 mutex_lock(&devlink->lock); 966 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 967 err = __sb_pool_get_dumpit(msg, start, &idx, devlink, 968 devlink_sb, 969 NETLINK_CB(cb->skb).portid, 970 cb->nlh->nlmsg_seq); 971 if (err && err != -EOPNOTSUPP) { 972 mutex_unlock(&devlink->lock); 973 goto out; 974 } 975 } 976 mutex_unlock(&devlink->lock); 977 } 978out: 979 mutex_unlock(&devlink_mutex); 980 981 cb->args[0] = idx; 982 return msg->len; 983} 984 985static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 986 u16 pool_index, u32 size, 987 enum devlink_sb_threshold_type threshold_type) 988 989{ 990 const struct devlink_ops *ops = devlink->ops; 991 992 if (ops && ops->sb_pool_set) 993 return ops->sb_pool_set(devlink, sb_index, pool_index, 994 size, threshold_type); 995 return -EOPNOTSUPP; 996} 997 998static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 999 struct genl_info *info) 1000{ 1001 struct devlink *devlink = info->user_ptr[0]; 1002 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1003 enum devlink_sb_threshold_type threshold_type; 1004 u16 pool_index; 1005 u32 size; 1006 int err; 1007 1008 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1009 &pool_index); 1010 if (err) 1011 return err; 1012 1013 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 1014 if (err) 1015 return err; 1016 1017 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) 1018 return -EINVAL; 1019 1020 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 1021 return devlink_sb_pool_set(devlink, devlink_sb->index, 1022 pool_index, size, threshold_type); 1023} 1024 1025static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 1026 struct devlink *devlink, 1027 struct devlink_port *devlink_port, 1028 struct devlink_sb *devlink_sb, 1029 u16 pool_index, 1030 enum devlink_command cmd, 1031 u32 portid, u32 seq, int flags) 1032{ 1033 const struct devlink_ops *ops = devlink->ops; 1034 u32 threshold; 1035 void *hdr; 1036 int err; 1037 1038 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 1039 pool_index, &threshold); 1040 if (err) 1041 return err; 1042 1043 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1044 if (!hdr) 1045 return -EMSGSIZE; 1046 1047 if (devlink_nl_put_handle(msg, devlink)) 1048 goto nla_put_failure; 1049 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1050 goto nla_put_failure; 1051 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1052 goto nla_put_failure; 1053 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1054 goto nla_put_failure; 1055 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1056 goto nla_put_failure; 1057 1058 if (ops->sb_occ_port_pool_get) { 1059 u32 cur; 1060 u32 max; 1061 1062 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 1063 pool_index, &cur, &max); 1064 if (err && err != -EOPNOTSUPP) 1065 return err; 1066 if (!err) { 1067 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1068 goto nla_put_failure; 1069 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1070 goto nla_put_failure; 1071 } 1072 } 1073 1074 genlmsg_end(msg, hdr); 1075 return 0; 1076 1077nla_put_failure: 1078 genlmsg_cancel(msg, hdr); 1079 return -EMSGSIZE; 1080} 1081 1082static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, 1083 struct genl_info *info) 1084{ 1085 struct devlink_port *devlink_port = info->user_ptr[0]; 1086 struct devlink *devlink = devlink_port->devlink; 1087 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1088 struct sk_buff *msg; 1089 u16 pool_index; 1090 int err; 1091 1092 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1093 &pool_index); 1094 if (err) 1095 return err; 1096 1097 if (!devlink->ops || !devlink->ops->sb_port_pool_get) 1098 return -EOPNOTSUPP; 1099 1100 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1101 if (!msg) 1102 return -ENOMEM; 1103 1104 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 1105 devlink_sb, pool_index, 1106 DEVLINK_CMD_SB_PORT_POOL_NEW, 1107 info->snd_portid, info->snd_seq, 0); 1108 if (err) { 1109 nlmsg_free(msg); 1110 return err; 1111 } 1112 1113 return genlmsg_reply(msg, info); 1114} 1115 1116static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1117 struct devlink *devlink, 1118 struct devlink_sb *devlink_sb, 1119 u32 portid, u32 seq) 1120{ 1121 struct devlink_port *devlink_port; 1122 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1123 u16 pool_index; 1124 int err; 1125 1126 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1127 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1128 if (*p_idx < start) { 1129 (*p_idx)++; 1130 continue; 1131 } 1132 err = devlink_nl_sb_port_pool_fill(msg, devlink, 1133 devlink_port, 1134 devlink_sb, 1135 pool_index, 1136 DEVLINK_CMD_SB_PORT_POOL_NEW, 1137 portid, seq, 1138 NLM_F_MULTI); 1139 if (err) 1140 return err; 1141 (*p_idx)++; 1142 } 1143 } 1144 return 0; 1145} 1146 1147static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, 1148 struct netlink_callback *cb) 1149{ 1150 struct devlink *devlink; 1151 struct devlink_sb *devlink_sb; 1152 int start = cb->args[0]; 1153 int idx = 0; 1154 int err; 1155 1156 mutex_lock(&devlink_mutex); 1157 list_for_each_entry(devlink, &devlink_list, list) { 1158 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1159 !devlink->ops || !devlink->ops->sb_port_pool_get) 1160 continue; 1161 mutex_lock(&devlink->lock); 1162 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1163 err = __sb_port_pool_get_dumpit(msg, start, &idx, 1164 devlink, devlink_sb, 1165 NETLINK_CB(cb->skb).portid, 1166 cb->nlh->nlmsg_seq); 1167 if (err && err != -EOPNOTSUPP) { 1168 mutex_unlock(&devlink->lock); 1169 goto out; 1170 } 1171 } 1172 mutex_unlock(&devlink->lock); 1173 } 1174out: 1175 mutex_unlock(&devlink_mutex); 1176 1177 cb->args[0] = idx; 1178 return msg->len; 1179} 1180 1181static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1182 unsigned int sb_index, u16 pool_index, 1183 u32 threshold) 1184 1185{ 1186 const struct devlink_ops *ops = devlink_port->devlink->ops; 1187 1188 if (ops && ops->sb_port_pool_set) 1189 return ops->sb_port_pool_set(devlink_port, sb_index, 1190 pool_index, threshold); 1191 return -EOPNOTSUPP; 1192} 1193 1194static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 1195 struct genl_info *info) 1196{ 1197 struct devlink_port *devlink_port = info->user_ptr[0]; 1198 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1199 u16 pool_index; 1200 u32 threshold; 1201 int err; 1202 1203 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1204 &pool_index); 1205 if (err) 1206 return err; 1207 1208 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1209 return -EINVAL; 1210 1211 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1212 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 1213 pool_index, threshold); 1214} 1215 1216static int 1217devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 1218 struct devlink_port *devlink_port, 1219 struct devlink_sb *devlink_sb, u16 tc_index, 1220 enum devlink_sb_pool_type pool_type, 1221 enum devlink_command cmd, 1222 u32 portid, u32 seq, int flags) 1223{ 1224 const struct devlink_ops *ops = devlink->ops; 1225 u16 pool_index; 1226 u32 threshold; 1227 void *hdr; 1228 int err; 1229 1230 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1231 tc_index, pool_type, 1232 &pool_index, &threshold); 1233 if (err) 1234 return err; 1235 1236 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1237 if (!hdr) 1238 return -EMSGSIZE; 1239 1240 if (devlink_nl_put_handle(msg, devlink)) 1241 goto nla_put_failure; 1242 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1243 goto nla_put_failure; 1244 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1245 goto nla_put_failure; 1246 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 1247 goto nla_put_failure; 1248 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 1249 goto nla_put_failure; 1250 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1251 goto nla_put_failure; 1252 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1253 goto nla_put_failure; 1254 1255 if (ops->sb_occ_tc_port_bind_get) { 1256 u32 cur; 1257 u32 max; 1258 1259 err = ops->sb_occ_tc_port_bind_get(devlink_port, 1260 devlink_sb->index, 1261 tc_index, pool_type, 1262 &cur, &max); 1263 if (err && err != -EOPNOTSUPP) 1264 return err; 1265 if (!err) { 1266 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1267 goto nla_put_failure; 1268 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1269 goto nla_put_failure; 1270 } 1271 } 1272 1273 genlmsg_end(msg, hdr); 1274 return 0; 1275 1276nla_put_failure: 1277 genlmsg_cancel(msg, hdr); 1278 return -EMSGSIZE; 1279} 1280 1281static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 1282 struct genl_info *info) 1283{ 1284 struct devlink_port *devlink_port = info->user_ptr[0]; 1285 struct devlink *devlink = devlink_port->devlink; 1286 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1287 struct sk_buff *msg; 1288 enum devlink_sb_pool_type pool_type; 1289 u16 tc_index; 1290 int err; 1291 1292 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1293 if (err) 1294 return err; 1295 1296 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1297 pool_type, &tc_index); 1298 if (err) 1299 return err; 1300 1301 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1302 return -EOPNOTSUPP; 1303 1304 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1305 if (!msg) 1306 return -ENOMEM; 1307 1308 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 1309 devlink_sb, tc_index, pool_type, 1310 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1311 info->snd_portid, 1312 info->snd_seq, 0); 1313 if (err) { 1314 nlmsg_free(msg); 1315 return err; 1316 } 1317 1318 return genlmsg_reply(msg, info); 1319} 1320 1321static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1322 int start, int *p_idx, 1323 struct devlink *devlink, 1324 struct devlink_sb *devlink_sb, 1325 u32 portid, u32 seq) 1326{ 1327 struct devlink_port *devlink_port; 1328 u16 tc_index; 1329 int err; 1330 1331 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1332 for (tc_index = 0; 1333 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 1334 if (*p_idx < start) { 1335 (*p_idx)++; 1336 continue; 1337 } 1338 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1339 devlink_port, 1340 devlink_sb, 1341 tc_index, 1342 DEVLINK_SB_POOL_TYPE_INGRESS, 1343 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1344 portid, seq, 1345 NLM_F_MULTI); 1346 if (err) 1347 return err; 1348 (*p_idx)++; 1349 } 1350 for (tc_index = 0; 1351 tc_index < devlink_sb->egress_tc_count; tc_index++) { 1352 if (*p_idx < start) { 1353 (*p_idx)++; 1354 continue; 1355 } 1356 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1357 devlink_port, 1358 devlink_sb, 1359 tc_index, 1360 DEVLINK_SB_POOL_TYPE_EGRESS, 1361 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1362 portid, seq, 1363 NLM_F_MULTI); 1364 if (err) 1365 return err; 1366 (*p_idx)++; 1367 } 1368 } 1369 return 0; 1370} 1371 1372static int 1373devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1374 struct netlink_callback *cb) 1375{ 1376 struct devlink *devlink; 1377 struct devlink_sb *devlink_sb; 1378 int start = cb->args[0]; 1379 int idx = 0; 1380 int err; 1381 1382 mutex_lock(&devlink_mutex); 1383 list_for_each_entry(devlink, &devlink_list, list) { 1384 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1385 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1386 continue; 1387 1388 mutex_lock(&devlink->lock); 1389 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1390 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, 1391 devlink, 1392 devlink_sb, 1393 NETLINK_CB(cb->skb).portid, 1394 cb->nlh->nlmsg_seq); 1395 if (err && err != -EOPNOTSUPP) { 1396 mutex_unlock(&devlink->lock); 1397 goto out; 1398 } 1399 } 1400 mutex_unlock(&devlink->lock); 1401 } 1402out: 1403 mutex_unlock(&devlink_mutex); 1404 1405 cb->args[0] = idx; 1406 return msg->len; 1407} 1408 1409static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1410 unsigned int sb_index, u16 tc_index, 1411 enum devlink_sb_pool_type pool_type, 1412 u16 pool_index, u32 threshold) 1413 1414{ 1415 const struct devlink_ops *ops = devlink_port->devlink->ops; 1416 1417 if (ops && ops->sb_tc_pool_bind_set) 1418 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 1419 tc_index, pool_type, 1420 pool_index, threshold); 1421 return -EOPNOTSUPP; 1422} 1423 1424static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 1425 struct genl_info *info) 1426{ 1427 struct devlink_port *devlink_port = info->user_ptr[0]; 1428 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1429 enum devlink_sb_pool_type pool_type; 1430 u16 tc_index; 1431 u16 pool_index; 1432 u32 threshold; 1433 int err; 1434 1435 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1436 if (err) 1437 return err; 1438 1439 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1440 pool_type, &tc_index); 1441 if (err) 1442 return err; 1443 1444 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1445 &pool_index); 1446 if (err) 1447 return err; 1448 1449 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1450 return -EINVAL; 1451 1452 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1453 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 1454 tc_index, pool_type, 1455 pool_index, threshold); 1456} 1457 1458static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 1459 struct genl_info *info) 1460{ 1461 struct devlink *devlink = info->user_ptr[0]; 1462 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1463 const struct devlink_ops *ops = devlink->ops; 1464 1465 if (ops && ops->sb_occ_snapshot) 1466 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 1467 return -EOPNOTSUPP; 1468} 1469 1470static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 1471 struct genl_info *info) 1472{ 1473 struct devlink *devlink = info->user_ptr[0]; 1474 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1475 const struct devlink_ops *ops = devlink->ops; 1476 1477 if (ops && ops->sb_occ_max_clear) 1478 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 1479 return -EOPNOTSUPP; 1480} 1481 1482static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, 1483 enum devlink_command cmd, u32 portid, 1484 u32 seq, int flags) 1485{ 1486 const struct devlink_ops *ops = devlink->ops; 1487 u8 inline_mode, encap_mode; 1488 void *hdr; 1489 int err = 0; 1490 u16 mode; 1491 1492 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1493 if (!hdr) 1494 return -EMSGSIZE; 1495 1496 err = devlink_nl_put_handle(msg, devlink); 1497 if (err) 1498 goto nla_put_failure; 1499 1500 if (ops->eswitch_mode_get) { 1501 err = ops->eswitch_mode_get(devlink, &mode); 1502 if (err) 1503 goto nla_put_failure; 1504 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode); 1505 if (err) 1506 goto nla_put_failure; 1507 } 1508 1509 if (ops->eswitch_inline_mode_get) { 1510 err = ops->eswitch_inline_mode_get(devlink, &inline_mode); 1511 if (err) 1512 goto nla_put_failure; 1513 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, 1514 inline_mode); 1515 if (err) 1516 goto nla_put_failure; 1517 } 1518 1519 if (ops->eswitch_encap_mode_get) { 1520 err = ops->eswitch_encap_mode_get(devlink, &encap_mode); 1521 if (err) 1522 goto nla_put_failure; 1523 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode); 1524 if (err) 1525 goto nla_put_failure; 1526 } 1527 1528 genlmsg_end(msg, hdr); 1529 return 0; 1530 1531nla_put_failure: 1532 genlmsg_cancel(msg, hdr); 1533 return err; 1534} 1535 1536static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, 1537 struct genl_info *info) 1538{ 1539 struct devlink *devlink = info->user_ptr[0]; 1540 const struct devlink_ops *ops = devlink->ops; 1541 struct sk_buff *msg; 1542 int err; 1543 1544 if (!ops) 1545 return -EOPNOTSUPP; 1546 1547 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1548 if (!msg) 1549 return -ENOMEM; 1550 1551 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET, 1552 info->snd_portid, info->snd_seq, 0); 1553 1554 if (err) { 1555 nlmsg_free(msg); 1556 return err; 1557 } 1558 1559 return genlmsg_reply(msg, info); 1560} 1561 1562static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, 1563 struct genl_info *info) 1564{ 1565 struct devlink *devlink = info->user_ptr[0]; 1566 const struct devlink_ops *ops = devlink->ops; 1567 u8 inline_mode, encap_mode; 1568 int err = 0; 1569 u16 mode; 1570 1571 if (!ops) 1572 return -EOPNOTSUPP; 1573 1574 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) { 1575 if (!ops->eswitch_mode_set) 1576 return -EOPNOTSUPP; 1577 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); 1578 err = ops->eswitch_mode_set(devlink, mode); 1579 if (err) 1580 return err; 1581 } 1582 1583 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { 1584 if (!ops->eswitch_inline_mode_set) 1585 return -EOPNOTSUPP; 1586 inline_mode = nla_get_u8( 1587 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]); 1588 err = ops->eswitch_inline_mode_set(devlink, inline_mode); 1589 if (err) 1590 return err; 1591 } 1592 1593 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) { 1594 if (!ops->eswitch_encap_mode_set) 1595 return -EOPNOTSUPP; 1596 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]); 1597 err = ops->eswitch_encap_mode_set(devlink, encap_mode); 1598 if (err) 1599 return err; 1600 } 1601 1602 return 0; 1603} 1604 1605int devlink_dpipe_match_put(struct sk_buff *skb, 1606 struct devlink_dpipe_match *match) 1607{ 1608 struct devlink_dpipe_header *header = match->header; 1609 struct devlink_dpipe_field *field = &header->fields[match->field_id]; 1610 struct nlattr *match_attr; 1611 1612 match_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_MATCH); 1613 if (!match_attr) 1614 return -EMSGSIZE; 1615 1616 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 1617 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 1618 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1619 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1620 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1621 goto nla_put_failure; 1622 1623 nla_nest_end(skb, match_attr); 1624 return 0; 1625 1626nla_put_failure: 1627 nla_nest_cancel(skb, match_attr); 1628 return -EMSGSIZE; 1629} 1630EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 1631 1632static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 1633 struct sk_buff *skb) 1634{ 1635 struct nlattr *matches_attr; 1636 1637 matches_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 1638 if (!matches_attr) 1639 return -EMSGSIZE; 1640 1641 if (table->table_ops->matches_dump(table->priv, skb)) 1642 goto nla_put_failure; 1643 1644 nla_nest_end(skb, matches_attr); 1645 return 0; 1646 1647nla_put_failure: 1648 nla_nest_cancel(skb, matches_attr); 1649 return -EMSGSIZE; 1650} 1651 1652int devlink_dpipe_action_put(struct sk_buff *skb, 1653 struct devlink_dpipe_action *action) 1654{ 1655 struct devlink_dpipe_header *header = action->header; 1656 struct devlink_dpipe_field *field = &header->fields[action->field_id]; 1657 struct nlattr *action_attr; 1658 1659 action_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ACTION); 1660 if (!action_attr) 1661 return -EMSGSIZE; 1662 1663 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 1664 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 1665 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1666 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1667 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1668 goto nla_put_failure; 1669 1670 nla_nest_end(skb, action_attr); 1671 return 0; 1672 1673nla_put_failure: 1674 nla_nest_cancel(skb, action_attr); 1675 return -EMSGSIZE; 1676} 1677EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 1678 1679static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 1680 struct sk_buff *skb) 1681{ 1682 struct nlattr *actions_attr; 1683 1684 actions_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 1685 if (!actions_attr) 1686 return -EMSGSIZE; 1687 1688 if (table->table_ops->actions_dump(table->priv, skb)) 1689 goto nla_put_failure; 1690 1691 nla_nest_end(skb, actions_attr); 1692 return 0; 1693 1694nla_put_failure: 1695 nla_nest_cancel(skb, actions_attr); 1696 return -EMSGSIZE; 1697} 1698 1699static int devlink_dpipe_table_put(struct sk_buff *skb, 1700 struct devlink_dpipe_table *table) 1701{ 1702 struct nlattr *table_attr; 1703 u64 table_size; 1704 1705 table_size = table->table_ops->size_get(table->priv); 1706 table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE); 1707 if (!table_attr) 1708 return -EMSGSIZE; 1709 1710 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 1711 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 1712 DEVLINK_ATTR_PAD)) 1713 goto nla_put_failure; 1714 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 1715 table->counters_enabled)) 1716 goto nla_put_failure; 1717 1718 if (table->resource_valid) { 1719 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 1720 table->resource_id, DEVLINK_ATTR_PAD) || 1721 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 1722 table->resource_units, DEVLINK_ATTR_PAD)) 1723 goto nla_put_failure; 1724 } 1725 if (devlink_dpipe_matches_put(table, skb)) 1726 goto nla_put_failure; 1727 1728 if (devlink_dpipe_actions_put(table, skb)) 1729 goto nla_put_failure; 1730 1731 nla_nest_end(skb, table_attr); 1732 return 0; 1733 1734nla_put_failure: 1735 nla_nest_cancel(skb, table_attr); 1736 return -EMSGSIZE; 1737} 1738 1739static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 1740 struct genl_info *info) 1741{ 1742 int err; 1743 1744 if (*pskb) { 1745 err = genlmsg_reply(*pskb, info); 1746 if (err) 1747 return err; 1748 } 1749 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1750 if (!*pskb) 1751 return -ENOMEM; 1752 return 0; 1753} 1754 1755static int devlink_dpipe_tables_fill(struct genl_info *info, 1756 enum devlink_command cmd, int flags, 1757 struct list_head *dpipe_tables, 1758 const char *table_name) 1759{ 1760 struct devlink *devlink = info->user_ptr[0]; 1761 struct devlink_dpipe_table *table; 1762 struct nlattr *tables_attr; 1763 struct sk_buff *skb = NULL; 1764 struct nlmsghdr *nlh; 1765 bool incomplete; 1766 void *hdr; 1767 int i; 1768 int err; 1769 1770 table = list_first_entry(dpipe_tables, 1771 struct devlink_dpipe_table, list); 1772start_again: 1773 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1774 if (err) 1775 return err; 1776 1777 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 1778 &devlink_nl_family, NLM_F_MULTI, cmd); 1779 if (!hdr) { 1780 nlmsg_free(skb); 1781 return -EMSGSIZE; 1782 } 1783 1784 if (devlink_nl_put_handle(skb, devlink)) 1785 goto nla_put_failure; 1786 tables_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLES); 1787 if (!tables_attr) 1788 goto nla_put_failure; 1789 1790 i = 0; 1791 incomplete = false; 1792 list_for_each_entry_from(table, dpipe_tables, list) { 1793 if (!table_name) { 1794 err = devlink_dpipe_table_put(skb, table); 1795 if (err) { 1796 if (!i) 1797 goto err_table_put; 1798 incomplete = true; 1799 break; 1800 } 1801 } else { 1802 if (!strcmp(table->name, table_name)) { 1803 err = devlink_dpipe_table_put(skb, table); 1804 if (err) 1805 break; 1806 } 1807 } 1808 i++; 1809 } 1810 1811 nla_nest_end(skb, tables_attr); 1812 genlmsg_end(skb, hdr); 1813 if (incomplete) 1814 goto start_again; 1815 1816send_done: 1817 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 1818 NLMSG_DONE, 0, flags | NLM_F_MULTI); 1819 if (!nlh) { 1820 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1821 if (err) 1822 return err; 1823 goto send_done; 1824 } 1825 1826 return genlmsg_reply(skb, info); 1827 1828nla_put_failure: 1829 err = -EMSGSIZE; 1830err_table_put: 1831 nlmsg_free(skb); 1832 return err; 1833} 1834 1835static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 1836 struct genl_info *info) 1837{ 1838 struct devlink *devlink = info->user_ptr[0]; 1839 const char *table_name = NULL; 1840 1841 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 1842 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 1843 1844 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 1845 &devlink->dpipe_table_list, 1846 table_name); 1847} 1848 1849static int devlink_dpipe_value_put(struct sk_buff *skb, 1850 struct devlink_dpipe_value *value) 1851{ 1852 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 1853 value->value_size, value->value)) 1854 return -EMSGSIZE; 1855 if (value->mask) 1856 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 1857 value->value_size, value->mask)) 1858 return -EMSGSIZE; 1859 if (value->mapping_valid) 1860 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 1861 value->mapping_value)) 1862 return -EMSGSIZE; 1863 return 0; 1864} 1865 1866static int devlink_dpipe_action_value_put(struct sk_buff *skb, 1867 struct devlink_dpipe_value *value) 1868{ 1869 if (!value->action) 1870 return -EINVAL; 1871 if (devlink_dpipe_action_put(skb, value->action)) 1872 return -EMSGSIZE; 1873 if (devlink_dpipe_value_put(skb, value)) 1874 return -EMSGSIZE; 1875 return 0; 1876} 1877 1878static int devlink_dpipe_action_values_put(struct sk_buff *skb, 1879 struct devlink_dpipe_value *values, 1880 unsigned int values_count) 1881{ 1882 struct nlattr *action_attr; 1883 int i; 1884 int err; 1885 1886 for (i = 0; i < values_count; i++) { 1887 action_attr = nla_nest_start(skb, 1888 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 1889 if (!action_attr) 1890 return -EMSGSIZE; 1891 err = devlink_dpipe_action_value_put(skb, &values[i]); 1892 if (err) 1893 goto err_action_value_put; 1894 nla_nest_end(skb, action_attr); 1895 } 1896 return 0; 1897 1898err_action_value_put: 1899 nla_nest_cancel(skb, action_attr); 1900 return err; 1901} 1902 1903static int devlink_dpipe_match_value_put(struct sk_buff *skb, 1904 struct devlink_dpipe_value *value) 1905{ 1906 if (!value->match) 1907 return -EINVAL; 1908 if (devlink_dpipe_match_put(skb, value->match)) 1909 return -EMSGSIZE; 1910 if (devlink_dpipe_value_put(skb, value)) 1911 return -EMSGSIZE; 1912 return 0; 1913} 1914 1915static int devlink_dpipe_match_values_put(struct sk_buff *skb, 1916 struct devlink_dpipe_value *values, 1917 unsigned int values_count) 1918{ 1919 struct nlattr *match_attr; 1920 int i; 1921 int err; 1922 1923 for (i = 0; i < values_count; i++) { 1924 match_attr = nla_nest_start(skb, 1925 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 1926 if (!match_attr) 1927 return -EMSGSIZE; 1928 err = devlink_dpipe_match_value_put(skb, &values[i]); 1929 if (err) 1930 goto err_match_value_put; 1931 nla_nest_end(skb, match_attr); 1932 } 1933 return 0; 1934 1935err_match_value_put: 1936 nla_nest_cancel(skb, match_attr); 1937 return err; 1938} 1939 1940static int devlink_dpipe_entry_put(struct sk_buff *skb, 1941 struct devlink_dpipe_entry *entry) 1942{ 1943 struct nlattr *entry_attr, *matches_attr, *actions_attr; 1944 int err; 1945 1946 entry_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ENTRY); 1947 if (!entry_attr) 1948 return -EMSGSIZE; 1949 1950 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 1951 DEVLINK_ATTR_PAD)) 1952 goto nla_put_failure; 1953 if (entry->counter_valid) 1954 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 1955 entry->counter, DEVLINK_ATTR_PAD)) 1956 goto nla_put_failure; 1957 1958 matches_attr = nla_nest_start(skb, 1959 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 1960 if (!matches_attr) 1961 goto nla_put_failure; 1962 1963 err = devlink_dpipe_match_values_put(skb, entry->match_values, 1964 entry->match_values_count); 1965 if (err) { 1966 nla_nest_cancel(skb, matches_attr); 1967 goto err_match_values_put; 1968 } 1969 nla_nest_end(skb, matches_attr); 1970 1971 actions_attr = nla_nest_start(skb, 1972 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 1973 if (!actions_attr) 1974 goto nla_put_failure; 1975 1976 err = devlink_dpipe_action_values_put(skb, entry->action_values, 1977 entry->action_values_count); 1978 if (err) { 1979 nla_nest_cancel(skb, actions_attr); 1980 goto err_action_values_put; 1981 } 1982 nla_nest_end(skb, actions_attr); 1983 1984 nla_nest_end(skb, entry_attr); 1985 return 0; 1986 1987nla_put_failure: 1988 err = -EMSGSIZE; 1989err_match_values_put: 1990err_action_values_put: 1991 nla_nest_cancel(skb, entry_attr); 1992 return err; 1993} 1994 1995static struct devlink_dpipe_table * 1996devlink_dpipe_table_find(struct list_head *dpipe_tables, 1997 const char *table_name) 1998{ 1999 struct devlink_dpipe_table *table; 2000 2001 list_for_each_entry_rcu(table, dpipe_tables, list) { 2002 if (!strcmp(table->name, table_name)) 2003 return table; 2004 } 2005 return NULL; 2006} 2007 2008int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 2009{ 2010 struct devlink *devlink; 2011 int err; 2012 2013 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 2014 dump_ctx->info); 2015 if (err) 2016 return err; 2017 2018 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 2019 dump_ctx->info->snd_portid, 2020 dump_ctx->info->snd_seq, 2021 &devlink_nl_family, NLM_F_MULTI, 2022 dump_ctx->cmd); 2023 if (!dump_ctx->hdr) 2024 goto nla_put_failure; 2025 2026 devlink = dump_ctx->info->user_ptr[0]; 2027 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2028 goto nla_put_failure; 2029 dump_ctx->nest = nla_nest_start(dump_ctx->skb, 2030 DEVLINK_ATTR_DPIPE_ENTRIES); 2031 if (!dump_ctx->nest) 2032 goto nla_put_failure; 2033 return 0; 2034 2035nla_put_failure: 2036 nlmsg_free(dump_ctx->skb); 2037 return -EMSGSIZE; 2038} 2039EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2040 2041int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2042 struct devlink_dpipe_entry *entry) 2043{ 2044 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2045} 2046EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2047 2048int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2049{ 2050 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2051 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2052 return 0; 2053} 2054EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2055 2056void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2057 2058{ 2059 unsigned int value_count, value_index; 2060 struct devlink_dpipe_value *value; 2061 2062 value = entry->action_values; 2063 value_count = entry->action_values_count; 2064 for (value_index = 0; value_index < value_count; value_index++) { 2065 kfree(value[value_index].value); 2066 kfree(value[value_index].mask); 2067 } 2068 2069 value = entry->match_values; 2070 value_count = entry->match_values_count; 2071 for (value_index = 0; value_index < value_count; value_index++) { 2072 kfree(value[value_index].value); 2073 kfree(value[value_index].mask); 2074 } 2075} 2076EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2077 2078static int devlink_dpipe_entries_fill(struct genl_info *info, 2079 enum devlink_command cmd, int flags, 2080 struct devlink_dpipe_table *table) 2081{ 2082 struct devlink_dpipe_dump_ctx dump_ctx; 2083 struct nlmsghdr *nlh; 2084 int err; 2085 2086 dump_ctx.skb = NULL; 2087 dump_ctx.cmd = cmd; 2088 dump_ctx.info = info; 2089 2090 err = table->table_ops->entries_dump(table->priv, 2091 table->counters_enabled, 2092 &dump_ctx); 2093 if (err) 2094 return err; 2095 2096send_done: 2097 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2098 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2099 if (!nlh) { 2100 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2101 if (err) 2102 return err; 2103 goto send_done; 2104 } 2105 return genlmsg_reply(dump_ctx.skb, info); 2106} 2107 2108static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2109 struct genl_info *info) 2110{ 2111 struct devlink *devlink = info->user_ptr[0]; 2112 struct devlink_dpipe_table *table; 2113 const char *table_name; 2114 2115 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2116 return -EINVAL; 2117 2118 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2119 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2120 table_name); 2121 if (!table) 2122 return -EINVAL; 2123 2124 if (!table->table_ops->entries_dump) 2125 return -EINVAL; 2126 2127 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2128 0, table); 2129} 2130 2131static int devlink_dpipe_fields_put(struct sk_buff *skb, 2132 const struct devlink_dpipe_header *header) 2133{ 2134 struct devlink_dpipe_field *field; 2135 struct nlattr *field_attr; 2136 int i; 2137 2138 for (i = 0; i < header->fields_count; i++) { 2139 field = &header->fields[i]; 2140 field_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_FIELD); 2141 if (!field_attr) 2142 return -EMSGSIZE; 2143 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2144 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2145 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2146 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2147 goto nla_put_failure; 2148 nla_nest_end(skb, field_attr); 2149 } 2150 return 0; 2151 2152nla_put_failure: 2153 nla_nest_cancel(skb, field_attr); 2154 return -EMSGSIZE; 2155} 2156 2157static int devlink_dpipe_header_put(struct sk_buff *skb, 2158 struct devlink_dpipe_header *header) 2159{ 2160 struct nlattr *fields_attr, *header_attr; 2161 int err; 2162 2163 header_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER); 2164 if (!header_attr) 2165 return -EMSGSIZE; 2166 2167 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2168 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2169 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2170 goto nla_put_failure; 2171 2172 fields_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2173 if (!fields_attr) 2174 goto nla_put_failure; 2175 2176 err = devlink_dpipe_fields_put(skb, header); 2177 if (err) { 2178 nla_nest_cancel(skb, fields_attr); 2179 goto nla_put_failure; 2180 } 2181 nla_nest_end(skb, fields_attr); 2182 nla_nest_end(skb, header_attr); 2183 return 0; 2184 2185nla_put_failure: 2186 err = -EMSGSIZE; 2187 nla_nest_cancel(skb, header_attr); 2188 return err; 2189} 2190 2191static int devlink_dpipe_headers_fill(struct genl_info *info, 2192 enum devlink_command cmd, int flags, 2193 struct devlink_dpipe_headers * 2194 dpipe_headers) 2195{ 2196 struct devlink *devlink = info->user_ptr[0]; 2197 struct nlattr *headers_attr; 2198 struct sk_buff *skb = NULL; 2199 struct nlmsghdr *nlh; 2200 void *hdr; 2201 int i, j; 2202 int err; 2203 2204 i = 0; 2205start_again: 2206 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2207 if (err) 2208 return err; 2209 2210 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2211 &devlink_nl_family, NLM_F_MULTI, cmd); 2212 if (!hdr) { 2213 nlmsg_free(skb); 2214 return -EMSGSIZE; 2215 } 2216 2217 if (devlink_nl_put_handle(skb, devlink)) 2218 goto nla_put_failure; 2219 headers_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2220 if (!headers_attr) 2221 goto nla_put_failure; 2222 2223 j = 0; 2224 for (; i < dpipe_headers->headers_count; i++) { 2225 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2226 if (err) { 2227 if (!j) 2228 goto err_table_put; 2229 break; 2230 } 2231 j++; 2232 } 2233 nla_nest_end(skb, headers_attr); 2234 genlmsg_end(skb, hdr); 2235 if (i != dpipe_headers->headers_count) 2236 goto start_again; 2237 2238send_done: 2239 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2240 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2241 if (!nlh) { 2242 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2243 if (err) 2244 return err; 2245 goto send_done; 2246 } 2247 return genlmsg_reply(skb, info); 2248 2249nla_put_failure: 2250 err = -EMSGSIZE; 2251err_table_put: 2252 nlmsg_free(skb); 2253 return err; 2254} 2255 2256static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2257 struct genl_info *info) 2258{ 2259 struct devlink *devlink = info->user_ptr[0]; 2260 2261 if (!devlink->dpipe_headers) 2262 return -EOPNOTSUPP; 2263 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2264 0, devlink->dpipe_headers); 2265} 2266 2267static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2268 const char *table_name, 2269 bool enable) 2270{ 2271 struct devlink_dpipe_table *table; 2272 2273 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2274 table_name); 2275 if (!table) 2276 return -EINVAL; 2277 2278 if (table->counter_control_extern) 2279 return -EOPNOTSUPP; 2280 2281 if (!(table->counters_enabled ^ enable)) 2282 return 0; 2283 2284 table->counters_enabled = enable; 2285 if (table->table_ops->counters_set_update) 2286 table->table_ops->counters_set_update(table->priv, enable); 2287 return 0; 2288} 2289 2290static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2291 struct genl_info *info) 2292{ 2293 struct devlink *devlink = info->user_ptr[0]; 2294 const char *table_name; 2295 bool counters_enable; 2296 2297 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2298 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2299 return -EINVAL; 2300 2301 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2302 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2303 2304 return devlink_dpipe_table_counters_set(devlink, table_name, 2305 counters_enable); 2306} 2307 2308static struct devlink_resource * 2309devlink_resource_find(struct devlink *devlink, 2310 struct devlink_resource *resource, u64 resource_id) 2311{ 2312 struct list_head *resource_list; 2313 2314 if (resource) 2315 resource_list = &resource->resource_list; 2316 else 2317 resource_list = &devlink->resource_list; 2318 2319 list_for_each_entry(resource, resource_list, list) { 2320 struct devlink_resource *child_resource; 2321 2322 if (resource->id == resource_id) 2323 return resource; 2324 2325 child_resource = devlink_resource_find(devlink, resource, 2326 resource_id); 2327 if (child_resource) 2328 return child_resource; 2329 } 2330 return NULL; 2331} 2332 2333static void 2334devlink_resource_validate_children(struct devlink_resource *resource) 2335{ 2336 struct devlink_resource *child_resource; 2337 bool size_valid = true; 2338 u64 parts_size = 0; 2339 2340 if (list_empty(&resource->resource_list)) 2341 goto out; 2342 2343 list_for_each_entry(child_resource, &resource->resource_list, list) 2344 parts_size += child_resource->size_new; 2345 2346 if (parts_size > resource->size_new) 2347 size_valid = false; 2348out: 2349 resource->size_valid = size_valid; 2350} 2351 2352static int 2353devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 2354 struct netlink_ext_ack *extack) 2355{ 2356 u64 reminder; 2357 int err = 0; 2358 2359 if (size > resource->size_params.size_max) { 2360 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum"); 2361 err = -EINVAL; 2362 } 2363 2364 if (size < resource->size_params.size_min) { 2365 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum"); 2366 err = -EINVAL; 2367 } 2368 2369 div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 2370 if (reminder) { 2371 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity"); 2372 err = -EINVAL; 2373 } 2374 2375 return err; 2376} 2377 2378static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2379 struct genl_info *info) 2380{ 2381 struct devlink *devlink = info->user_ptr[0]; 2382 struct devlink_resource *resource; 2383 u64 resource_id; 2384 u64 size; 2385 int err; 2386 2387 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2388 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2389 return -EINVAL; 2390 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2391 2392 resource = devlink_resource_find(devlink, NULL, resource_id); 2393 if (!resource) 2394 return -EINVAL; 2395 2396 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2397 err = devlink_resource_validate_size(resource, size, info->extack); 2398 if (err) 2399 return err; 2400 2401 resource->size_new = size; 2402 devlink_resource_validate_children(resource); 2403 if (resource->parent) 2404 devlink_resource_validate_children(resource->parent); 2405 return 0; 2406} 2407 2408static int 2409devlink_resource_size_params_put(struct devlink_resource *resource, 2410 struct sk_buff *skb) 2411{ 2412 struct devlink_resource_size_params *size_params; 2413 2414 size_params = &resource->size_params; 2415 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2416 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2417 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2418 size_params->size_max, DEVLINK_ATTR_PAD) || 2419 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2420 size_params->size_min, DEVLINK_ATTR_PAD) || 2421 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2422 return -EMSGSIZE; 2423 return 0; 2424} 2425 2426static int devlink_resource_occ_put(struct devlink_resource *resource, 2427 struct sk_buff *skb) 2428{ 2429 if (!resource->occ_get) 2430 return 0; 2431 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2432 resource->occ_get(resource->occ_get_priv), 2433 DEVLINK_ATTR_PAD); 2434} 2435 2436static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2437 struct devlink_resource *resource) 2438{ 2439 struct devlink_resource *child_resource; 2440 struct nlattr *child_resource_attr; 2441 struct nlattr *resource_attr; 2442 2443 resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE); 2444 if (!resource_attr) 2445 return -EMSGSIZE; 2446 2447 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2448 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2449 DEVLINK_ATTR_PAD) || 2450 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2451 DEVLINK_ATTR_PAD)) 2452 goto nla_put_failure; 2453 if (resource->size != resource->size_new) 2454 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2455 resource->size_new, DEVLINK_ATTR_PAD); 2456 if (devlink_resource_occ_put(resource, skb)) 2457 goto nla_put_failure; 2458 if (devlink_resource_size_params_put(resource, skb)) 2459 goto nla_put_failure; 2460 if (list_empty(&resource->resource_list)) 2461 goto out; 2462 2463 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2464 resource->size_valid)) 2465 goto nla_put_failure; 2466 2467 child_resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2468 if (!child_resource_attr) 2469 goto nla_put_failure; 2470 2471 list_for_each_entry(child_resource, &resource->resource_list, list) { 2472 if (devlink_resource_put(devlink, skb, child_resource)) 2473 goto resource_put_failure; 2474 } 2475 2476 nla_nest_end(skb, child_resource_attr); 2477out: 2478 nla_nest_end(skb, resource_attr); 2479 return 0; 2480 2481resource_put_failure: 2482 nla_nest_cancel(skb, child_resource_attr); 2483nla_put_failure: 2484 nla_nest_cancel(skb, resource_attr); 2485 return -EMSGSIZE; 2486} 2487 2488static int devlink_resource_fill(struct genl_info *info, 2489 enum devlink_command cmd, int flags) 2490{ 2491 struct devlink *devlink = info->user_ptr[0]; 2492 struct devlink_resource *resource; 2493 struct nlattr *resources_attr; 2494 struct sk_buff *skb = NULL; 2495 struct nlmsghdr *nlh; 2496 bool incomplete; 2497 void *hdr; 2498 int i; 2499 int err; 2500 2501 resource = list_first_entry(&devlink->resource_list, 2502 struct devlink_resource, list); 2503start_again: 2504 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2505 if (err) 2506 return err; 2507 2508 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2509 &devlink_nl_family, NLM_F_MULTI, cmd); 2510 if (!hdr) { 2511 nlmsg_free(skb); 2512 return -EMSGSIZE; 2513 } 2514 2515 if (devlink_nl_put_handle(skb, devlink)) 2516 goto nla_put_failure; 2517 2518 resources_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2519 if (!resources_attr) 2520 goto nla_put_failure; 2521 2522 incomplete = false; 2523 i = 0; 2524 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2525 err = devlink_resource_put(devlink, skb, resource); 2526 if (err) { 2527 if (!i) 2528 goto err_resource_put; 2529 incomplete = true; 2530 break; 2531 } 2532 i++; 2533 } 2534 nla_nest_end(skb, resources_attr); 2535 genlmsg_end(skb, hdr); 2536 if (incomplete) 2537 goto start_again; 2538send_done: 2539 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2540 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2541 if (!nlh) { 2542 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2543 if (err) 2544 goto err_skb_send_alloc; 2545 goto send_done; 2546 } 2547 return genlmsg_reply(skb, info); 2548 2549nla_put_failure: 2550 err = -EMSGSIZE; 2551err_resource_put: 2552err_skb_send_alloc: 2553 nlmsg_free(skb); 2554 return err; 2555} 2556 2557static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2558 struct genl_info *info) 2559{ 2560 struct devlink *devlink = info->user_ptr[0]; 2561 2562 if (list_empty(&devlink->resource_list)) 2563 return -EOPNOTSUPP; 2564 2565 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2566} 2567 2568static int 2569devlink_resources_validate(struct devlink *devlink, 2570 struct devlink_resource *resource, 2571 struct genl_info *info) 2572{ 2573 struct list_head *resource_list; 2574 int err = 0; 2575 2576 if (resource) 2577 resource_list = &resource->resource_list; 2578 else 2579 resource_list = &devlink->resource_list; 2580 2581 list_for_each_entry(resource, resource_list, list) { 2582 if (!resource->size_valid) 2583 return -EINVAL; 2584 err = devlink_resources_validate(devlink, resource, info); 2585 if (err) 2586 return err; 2587 } 2588 return err; 2589} 2590 2591static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2592{ 2593 struct devlink *devlink = info->user_ptr[0]; 2594 int err; 2595 2596 if (!devlink->ops->reload) 2597 return -EOPNOTSUPP; 2598 2599 err = devlink_resources_validate(devlink, NULL, info); 2600 if (err) { 2601 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2602 return err; 2603 } 2604 return devlink->ops->reload(devlink, info->extack); 2605} 2606 2607static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 2608 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 2609 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 2610 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 2611 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 2612 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 2613 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 2614 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 2615 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 2616 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 2617 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 2618 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 2619 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 2620 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 2621 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 2622 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 2623 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 2624 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 2625 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 2626 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 2627}; 2628 2629static const struct genl_ops devlink_nl_ops[] = { 2630 { 2631 .cmd = DEVLINK_CMD_GET, 2632 .doit = devlink_nl_cmd_get_doit, 2633 .dumpit = devlink_nl_cmd_get_dumpit, 2634 .policy = devlink_nl_policy, 2635 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2636 /* can be retrieved by unprivileged users */ 2637 }, 2638 { 2639 .cmd = DEVLINK_CMD_PORT_GET, 2640 .doit = devlink_nl_cmd_port_get_doit, 2641 .dumpit = devlink_nl_cmd_port_get_dumpit, 2642 .policy = devlink_nl_policy, 2643 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 2644 /* can be retrieved by unprivileged users */ 2645 }, 2646 { 2647 .cmd = DEVLINK_CMD_PORT_SET, 2648 .doit = devlink_nl_cmd_port_set_doit, 2649 .policy = devlink_nl_policy, 2650 .flags = GENL_ADMIN_PERM, 2651 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 2652 }, 2653 { 2654 .cmd = DEVLINK_CMD_PORT_SPLIT, 2655 .doit = devlink_nl_cmd_port_split_doit, 2656 .policy = devlink_nl_policy, 2657 .flags = GENL_ADMIN_PERM, 2658 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2659 DEVLINK_NL_FLAG_NO_LOCK, 2660 }, 2661 { 2662 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 2663 .doit = devlink_nl_cmd_port_unsplit_doit, 2664 .policy = devlink_nl_policy, 2665 .flags = GENL_ADMIN_PERM, 2666 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2667 DEVLINK_NL_FLAG_NO_LOCK, 2668 }, 2669 { 2670 .cmd = DEVLINK_CMD_SB_GET, 2671 .doit = devlink_nl_cmd_sb_get_doit, 2672 .dumpit = devlink_nl_cmd_sb_get_dumpit, 2673 .policy = devlink_nl_policy, 2674 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2675 DEVLINK_NL_FLAG_NEED_SB, 2676 /* can be retrieved by unprivileged users */ 2677 }, 2678 { 2679 .cmd = DEVLINK_CMD_SB_POOL_GET, 2680 .doit = devlink_nl_cmd_sb_pool_get_doit, 2681 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 2682 .policy = devlink_nl_policy, 2683 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2684 DEVLINK_NL_FLAG_NEED_SB, 2685 /* can be retrieved by unprivileged users */ 2686 }, 2687 { 2688 .cmd = DEVLINK_CMD_SB_POOL_SET, 2689 .doit = devlink_nl_cmd_sb_pool_set_doit, 2690 .policy = devlink_nl_policy, 2691 .flags = GENL_ADMIN_PERM, 2692 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2693 DEVLINK_NL_FLAG_NEED_SB, 2694 }, 2695 { 2696 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 2697 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 2698 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 2699 .policy = devlink_nl_policy, 2700 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2701 DEVLINK_NL_FLAG_NEED_SB, 2702 /* can be retrieved by unprivileged users */ 2703 }, 2704 { 2705 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 2706 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 2707 .policy = devlink_nl_policy, 2708 .flags = GENL_ADMIN_PERM, 2709 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2710 DEVLINK_NL_FLAG_NEED_SB, 2711 }, 2712 { 2713 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 2714 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 2715 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 2716 .policy = devlink_nl_policy, 2717 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2718 DEVLINK_NL_FLAG_NEED_SB, 2719 /* can be retrieved by unprivileged users */ 2720 }, 2721 { 2722 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 2723 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 2724 .policy = devlink_nl_policy, 2725 .flags = GENL_ADMIN_PERM, 2726 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2727 DEVLINK_NL_FLAG_NEED_SB, 2728 }, 2729 { 2730 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 2731 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 2732 .policy = devlink_nl_policy, 2733 .flags = GENL_ADMIN_PERM, 2734 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2735 DEVLINK_NL_FLAG_NEED_SB, 2736 }, 2737 { 2738 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 2739 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 2740 .policy = devlink_nl_policy, 2741 .flags = GENL_ADMIN_PERM, 2742 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2743 DEVLINK_NL_FLAG_NEED_SB, 2744 }, 2745 { 2746 .cmd = DEVLINK_CMD_ESWITCH_GET, 2747 .doit = devlink_nl_cmd_eswitch_get_doit, 2748 .policy = devlink_nl_policy, 2749 .flags = GENL_ADMIN_PERM, 2750 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2751 }, 2752 { 2753 .cmd = DEVLINK_CMD_ESWITCH_SET, 2754 .doit = devlink_nl_cmd_eswitch_set_doit, 2755 .policy = devlink_nl_policy, 2756 .flags = GENL_ADMIN_PERM, 2757 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2758 DEVLINK_NL_FLAG_NO_LOCK, 2759 }, 2760 { 2761 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 2762 .doit = devlink_nl_cmd_dpipe_table_get, 2763 .policy = devlink_nl_policy, 2764 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2765 /* can be retrieved by unprivileged users */ 2766 }, 2767 { 2768 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 2769 .doit = devlink_nl_cmd_dpipe_entries_get, 2770 .policy = devlink_nl_policy, 2771 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2772 /* can be retrieved by unprivileged users */ 2773 }, 2774 { 2775 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 2776 .doit = devlink_nl_cmd_dpipe_headers_get, 2777 .policy = devlink_nl_policy, 2778 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2779 /* can be retrieved by unprivileged users */ 2780 }, 2781 { 2782 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 2783 .doit = devlink_nl_cmd_dpipe_table_counters_set, 2784 .policy = devlink_nl_policy, 2785 .flags = GENL_ADMIN_PERM, 2786 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2787 }, 2788 { 2789 .cmd = DEVLINK_CMD_RESOURCE_SET, 2790 .doit = devlink_nl_cmd_resource_set, 2791 .policy = devlink_nl_policy, 2792 .flags = GENL_ADMIN_PERM, 2793 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2794 }, 2795 { 2796 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 2797 .doit = devlink_nl_cmd_resource_dump, 2798 .policy = devlink_nl_policy, 2799 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2800 /* can be retrieved by unprivileged users */ 2801 }, 2802 { 2803 .cmd = DEVLINK_CMD_RELOAD, 2804 .doit = devlink_nl_cmd_reload, 2805 .policy = devlink_nl_policy, 2806 .flags = GENL_ADMIN_PERM, 2807 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2808 DEVLINK_NL_FLAG_NO_LOCK, 2809 }, 2810}; 2811 2812static struct genl_family devlink_nl_family __ro_after_init = { 2813 .name = DEVLINK_GENL_NAME, 2814 .version = DEVLINK_GENL_VERSION, 2815 .maxattr = DEVLINK_ATTR_MAX, 2816 .netnsok = true, 2817 .pre_doit = devlink_nl_pre_doit, 2818 .post_doit = devlink_nl_post_doit, 2819 .module = THIS_MODULE, 2820 .ops = devlink_nl_ops, 2821 .n_ops = ARRAY_SIZE(devlink_nl_ops), 2822 .mcgrps = devlink_nl_mcgrps, 2823 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 2824}; 2825 2826/** 2827 * devlink_alloc - Allocate new devlink instance resources 2828 * 2829 * @ops: ops 2830 * @priv_size: size of user private data 2831 * 2832 * Allocate new devlink instance resources, including devlink index 2833 * and name. 2834 */ 2835struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 2836{ 2837 struct devlink *devlink; 2838 2839 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 2840 if (!devlink) 2841 return NULL; 2842 devlink->ops = ops; 2843 devlink_net_set(devlink, &init_net); 2844 INIT_LIST_HEAD(&devlink->port_list); 2845 INIT_LIST_HEAD(&devlink->sb_list); 2846 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 2847 INIT_LIST_HEAD(&devlink->resource_list); 2848 mutex_init(&devlink->lock); 2849 return devlink; 2850} 2851EXPORT_SYMBOL_GPL(devlink_alloc); 2852 2853/** 2854 * devlink_register - Register devlink instance 2855 * 2856 * @devlink: devlink 2857 */ 2858int devlink_register(struct devlink *devlink, struct device *dev) 2859{ 2860 mutex_lock(&devlink_mutex); 2861 devlink->dev = dev; 2862 list_add_tail(&devlink->list, &devlink_list); 2863 devlink_notify(devlink, DEVLINK_CMD_NEW); 2864 mutex_unlock(&devlink_mutex); 2865 return 0; 2866} 2867EXPORT_SYMBOL_GPL(devlink_register); 2868 2869/** 2870 * devlink_unregister - Unregister devlink instance 2871 * 2872 * @devlink: devlink 2873 */ 2874void devlink_unregister(struct devlink *devlink) 2875{ 2876 mutex_lock(&devlink_mutex); 2877 devlink_notify(devlink, DEVLINK_CMD_DEL); 2878 list_del(&devlink->list); 2879 mutex_unlock(&devlink_mutex); 2880} 2881EXPORT_SYMBOL_GPL(devlink_unregister); 2882 2883/** 2884 * devlink_free - Free devlink instance resources 2885 * 2886 * @devlink: devlink 2887 */ 2888void devlink_free(struct devlink *devlink) 2889{ 2890 kfree(devlink); 2891} 2892EXPORT_SYMBOL_GPL(devlink_free); 2893 2894/** 2895 * devlink_port_register - Register devlink port 2896 * 2897 * @devlink: devlink 2898 * @devlink_port: devlink port 2899 * @port_index 2900 * 2901 * Register devlink port with provided port index. User can use 2902 * any indexing, even hw-related one. devlink_port structure 2903 * is convenient to be embedded inside user driver private structure. 2904 * Note that the caller should take care of zeroing the devlink_port 2905 * structure. 2906 */ 2907int devlink_port_register(struct devlink *devlink, 2908 struct devlink_port *devlink_port, 2909 unsigned int port_index) 2910{ 2911 mutex_lock(&devlink->lock); 2912 if (devlink_port_index_exists(devlink, port_index)) { 2913 mutex_unlock(&devlink->lock); 2914 return -EEXIST; 2915 } 2916 devlink_port->devlink = devlink; 2917 devlink_port->index = port_index; 2918 devlink_port->registered = true; 2919 list_add_tail(&devlink_port->list, &devlink->port_list); 2920 mutex_unlock(&devlink->lock); 2921 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2922 return 0; 2923} 2924EXPORT_SYMBOL_GPL(devlink_port_register); 2925 2926/** 2927 * devlink_port_unregister - Unregister devlink port 2928 * 2929 * @devlink_port: devlink port 2930 */ 2931void devlink_port_unregister(struct devlink_port *devlink_port) 2932{ 2933 struct devlink *devlink = devlink_port->devlink; 2934 2935 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 2936 mutex_lock(&devlink->lock); 2937 list_del(&devlink_port->list); 2938 mutex_unlock(&devlink->lock); 2939} 2940EXPORT_SYMBOL_GPL(devlink_port_unregister); 2941 2942static void __devlink_port_type_set(struct devlink_port *devlink_port, 2943 enum devlink_port_type type, 2944 void *type_dev) 2945{ 2946 devlink_port->type = type; 2947 devlink_port->type_dev = type_dev; 2948 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2949} 2950 2951/** 2952 * devlink_port_type_eth_set - Set port type to Ethernet 2953 * 2954 * @devlink_port: devlink port 2955 * @netdev: related netdevice 2956 */ 2957void devlink_port_type_eth_set(struct devlink_port *devlink_port, 2958 struct net_device *netdev) 2959{ 2960 return __devlink_port_type_set(devlink_port, 2961 DEVLINK_PORT_TYPE_ETH, netdev); 2962} 2963EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 2964 2965/** 2966 * devlink_port_type_ib_set - Set port type to InfiniBand 2967 * 2968 * @devlink_port: devlink port 2969 * @ibdev: related IB device 2970 */ 2971void devlink_port_type_ib_set(struct devlink_port *devlink_port, 2972 struct ib_device *ibdev) 2973{ 2974 return __devlink_port_type_set(devlink_port, 2975 DEVLINK_PORT_TYPE_IB, ibdev); 2976} 2977EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 2978 2979/** 2980 * devlink_port_type_clear - Clear port type 2981 * 2982 * @devlink_port: devlink port 2983 */ 2984void devlink_port_type_clear(struct devlink_port *devlink_port) 2985{ 2986 return __devlink_port_type_set(devlink_port, 2987 DEVLINK_PORT_TYPE_NOTSET, NULL); 2988} 2989EXPORT_SYMBOL_GPL(devlink_port_type_clear); 2990 2991/** 2992 * devlink_port_attrs_set - Set port attributes 2993 * 2994 * @devlink_port: devlink port 2995 * @flavour: flavour of the port 2996 * @port_number: number of the port that is facing user, for example 2997 * the front panel port number 2998 * @split: indicates if this is split port 2999 * @split_subport_number: if the port is split, this is the number 3000 * of subport. 3001 */ 3002void devlink_port_attrs_set(struct devlink_port *devlink_port, 3003 enum devlink_port_flavour flavour, 3004 u32 port_number, bool split, 3005 u32 split_subport_number) 3006{ 3007 struct devlink_port_attrs *attrs = &devlink_port->attrs; 3008 3009 attrs->set = true; 3010 attrs->flavour = flavour; 3011 attrs->port_number = port_number; 3012 attrs->split = split; 3013 attrs->split_subport_number = split_subport_number; 3014 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3015} 3016EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 3017 3018int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, 3019 char *name, size_t len) 3020{ 3021 struct devlink_port_attrs *attrs = &devlink_port->attrs; 3022 int n = 0; 3023 3024 if (!attrs->set) 3025 return -EOPNOTSUPP; 3026 3027 switch (attrs->flavour) { 3028 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 3029 if (!attrs->split) 3030 n = snprintf(name, len, "p%u", attrs->port_number); 3031 else 3032 n = snprintf(name, len, "p%us%u", attrs->port_number, 3033 attrs->split_subport_number); 3034 break; 3035 case DEVLINK_PORT_FLAVOUR_CPU: 3036 case DEVLINK_PORT_FLAVOUR_DSA: 3037 /* As CPU and DSA ports do not have a netdevice associated 3038 * case should not ever happen. 3039 */ 3040 WARN_ON(1); 3041 return -EINVAL; 3042 } 3043 3044 if (n >= len) 3045 return -EINVAL; 3046 3047 return 0; 3048} 3049EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name); 3050 3051int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 3052 u32 size, u16 ingress_pools_count, 3053 u16 egress_pools_count, u16 ingress_tc_count, 3054 u16 egress_tc_count) 3055{ 3056 struct devlink_sb *devlink_sb; 3057 int err = 0; 3058 3059 mutex_lock(&devlink->lock); 3060 if (devlink_sb_index_exists(devlink, sb_index)) { 3061 err = -EEXIST; 3062 goto unlock; 3063 } 3064 3065 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 3066 if (!devlink_sb) { 3067 err = -ENOMEM; 3068 goto unlock; 3069 } 3070 devlink_sb->index = sb_index; 3071 devlink_sb->size = size; 3072 devlink_sb->ingress_pools_count = ingress_pools_count; 3073 devlink_sb->egress_pools_count = egress_pools_count; 3074 devlink_sb->ingress_tc_count = ingress_tc_count; 3075 devlink_sb->egress_tc_count = egress_tc_count; 3076 list_add_tail(&devlink_sb->list, &devlink->sb_list); 3077unlock: 3078 mutex_unlock(&devlink->lock); 3079 return err; 3080} 3081EXPORT_SYMBOL_GPL(devlink_sb_register); 3082 3083void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 3084{ 3085 struct devlink_sb *devlink_sb; 3086 3087 mutex_lock(&devlink->lock); 3088 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 3089 WARN_ON(!devlink_sb); 3090 list_del(&devlink_sb->list); 3091 mutex_unlock(&devlink->lock); 3092 kfree(devlink_sb); 3093} 3094EXPORT_SYMBOL_GPL(devlink_sb_unregister); 3095 3096/** 3097 * devlink_dpipe_headers_register - register dpipe headers 3098 * 3099 * @devlink: devlink 3100 * @dpipe_headers: dpipe header array 3101 * 3102 * Register the headers supported by hardware. 3103 */ 3104int devlink_dpipe_headers_register(struct devlink *devlink, 3105 struct devlink_dpipe_headers *dpipe_headers) 3106{ 3107 mutex_lock(&devlink->lock); 3108 devlink->dpipe_headers = dpipe_headers; 3109 mutex_unlock(&devlink->lock); 3110 return 0; 3111} 3112EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 3113 3114/** 3115 * devlink_dpipe_headers_unregister - unregister dpipe headers 3116 * 3117 * @devlink: devlink 3118 * 3119 * Unregister the headers supported by hardware. 3120 */ 3121void devlink_dpipe_headers_unregister(struct devlink *devlink) 3122{ 3123 mutex_lock(&devlink->lock); 3124 devlink->dpipe_headers = NULL; 3125 mutex_unlock(&devlink->lock); 3126} 3127EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 3128 3129/** 3130 * devlink_dpipe_table_counter_enabled - check if counter allocation 3131 * required 3132 * @devlink: devlink 3133 * @table_name: tables name 3134 * 3135 * Used by driver to check if counter allocation is required. 3136 * After counter allocation is turned on the table entries 3137 * are updated to include counter statistics. 3138 * 3139 * After that point on the driver must respect the counter 3140 * state so that each entry added to the table is added 3141 * with a counter. 3142 */ 3143bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 3144 const char *table_name) 3145{ 3146 struct devlink_dpipe_table *table; 3147 bool enabled; 3148 3149 rcu_read_lock(); 3150 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3151 table_name); 3152 enabled = false; 3153 if (table) 3154 enabled = table->counters_enabled; 3155 rcu_read_unlock(); 3156 return enabled; 3157} 3158EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 3159 3160/** 3161 * devlink_dpipe_table_register - register dpipe table 3162 * 3163 * @devlink: devlink 3164 * @table_name: table name 3165 * @table_ops: table ops 3166 * @priv: priv 3167 * @counter_control_extern: external control for counters 3168 */ 3169int devlink_dpipe_table_register(struct devlink *devlink, 3170 const char *table_name, 3171 struct devlink_dpipe_table_ops *table_ops, 3172 void *priv, bool counter_control_extern) 3173{ 3174 struct devlink_dpipe_table *table; 3175 3176 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 3177 return -EEXIST; 3178 3179 if (WARN_ON(!table_ops->size_get)) 3180 return -EINVAL; 3181 3182 table = kzalloc(sizeof(*table), GFP_KERNEL); 3183 if (!table) 3184 return -ENOMEM; 3185 3186 table->name = table_name; 3187 table->table_ops = table_ops; 3188 table->priv = priv; 3189 table->counter_control_extern = counter_control_extern; 3190 3191 mutex_lock(&devlink->lock); 3192 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 3193 mutex_unlock(&devlink->lock); 3194 return 0; 3195} 3196EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 3197 3198/** 3199 * devlink_dpipe_table_unregister - unregister dpipe table 3200 * 3201 * @devlink: devlink 3202 * @table_name: table name 3203 */ 3204void devlink_dpipe_table_unregister(struct devlink *devlink, 3205 const char *table_name) 3206{ 3207 struct devlink_dpipe_table *table; 3208 3209 mutex_lock(&devlink->lock); 3210 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3211 table_name); 3212 if (!table) 3213 goto unlock; 3214 list_del_rcu(&table->list); 3215 mutex_unlock(&devlink->lock); 3216 kfree_rcu(table, rcu); 3217 return; 3218unlock: 3219 mutex_unlock(&devlink->lock); 3220} 3221EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 3222 3223/** 3224 * devlink_resource_register - devlink resource register 3225 * 3226 * @devlink: devlink 3227 * @resource_name: resource's name 3228 * @top_hierarchy: top hierarchy 3229 * @reload_required: reload is required for new configuration to 3230 * apply 3231 * @resource_size: resource's size 3232 * @resource_id: resource's id 3233 * @parent_reosurce_id: resource's parent id 3234 * @size params: size parameters 3235 */ 3236int devlink_resource_register(struct devlink *devlink, 3237 const char *resource_name, 3238 u64 resource_size, 3239 u64 resource_id, 3240 u64 parent_resource_id, 3241 const struct devlink_resource_size_params *size_params) 3242{ 3243 struct devlink_resource *resource; 3244 struct list_head *resource_list; 3245 bool top_hierarchy; 3246 int err = 0; 3247 3248 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 3249 3250 mutex_lock(&devlink->lock); 3251 resource = devlink_resource_find(devlink, NULL, resource_id); 3252 if (resource) { 3253 err = -EINVAL; 3254 goto out; 3255 } 3256 3257 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 3258 if (!resource) { 3259 err = -ENOMEM; 3260 goto out; 3261 } 3262 3263 if (top_hierarchy) { 3264 resource_list = &devlink->resource_list; 3265 } else { 3266 struct devlink_resource *parent_resource; 3267 3268 parent_resource = devlink_resource_find(devlink, NULL, 3269 parent_resource_id); 3270 if (parent_resource) { 3271 resource_list = &parent_resource->resource_list; 3272 resource->parent = parent_resource; 3273 } else { 3274 kfree(resource); 3275 err = -EINVAL; 3276 goto out; 3277 } 3278 } 3279 3280 resource->name = resource_name; 3281 resource->size = resource_size; 3282 resource->size_new = resource_size; 3283 resource->id = resource_id; 3284 resource->size_valid = true; 3285 memcpy(&resource->size_params, size_params, 3286 sizeof(resource->size_params)); 3287 INIT_LIST_HEAD(&resource->resource_list); 3288 list_add_tail(&resource->list, resource_list); 3289out: 3290 mutex_unlock(&devlink->lock); 3291 return err; 3292} 3293EXPORT_SYMBOL_GPL(devlink_resource_register); 3294 3295/** 3296 * devlink_resources_unregister - free all resources 3297 * 3298 * @devlink: devlink 3299 * @resource: resource 3300 */ 3301void devlink_resources_unregister(struct devlink *devlink, 3302 struct devlink_resource *resource) 3303{ 3304 struct devlink_resource *tmp, *child_resource; 3305 struct list_head *resource_list; 3306 3307 if (resource) 3308 resource_list = &resource->resource_list; 3309 else 3310 resource_list = &devlink->resource_list; 3311 3312 if (!resource) 3313 mutex_lock(&devlink->lock); 3314 3315 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 3316 devlink_resources_unregister(devlink, child_resource); 3317 list_del(&child_resource->list); 3318 kfree(child_resource); 3319 } 3320 3321 if (!resource) 3322 mutex_unlock(&devlink->lock); 3323} 3324EXPORT_SYMBOL_GPL(devlink_resources_unregister); 3325 3326/** 3327 * devlink_resource_size_get - get and update size 3328 * 3329 * @devlink: devlink 3330 * @resource_id: the requested resource id 3331 * @p_resource_size: ptr to update 3332 */ 3333int devlink_resource_size_get(struct devlink *devlink, 3334 u64 resource_id, 3335 u64 *p_resource_size) 3336{ 3337 struct devlink_resource *resource; 3338 int err = 0; 3339 3340 mutex_lock(&devlink->lock); 3341 resource = devlink_resource_find(devlink, NULL, resource_id); 3342 if (!resource) { 3343 err = -EINVAL; 3344 goto out; 3345 } 3346 *p_resource_size = resource->size_new; 3347 resource->size = resource->size_new; 3348out: 3349 mutex_unlock(&devlink->lock); 3350 return err; 3351} 3352EXPORT_SYMBOL_GPL(devlink_resource_size_get); 3353 3354/** 3355 * devlink_dpipe_table_resource_set - set the resource id 3356 * 3357 * @devlink: devlink 3358 * @table_name: table name 3359 * @resource_id: resource id 3360 * @resource_units: number of resource's units consumed per table's entry 3361 */ 3362int devlink_dpipe_table_resource_set(struct devlink *devlink, 3363 const char *table_name, u64 resource_id, 3364 u64 resource_units) 3365{ 3366 struct devlink_dpipe_table *table; 3367 int err = 0; 3368 3369 mutex_lock(&devlink->lock); 3370 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3371 table_name); 3372 if (!table) { 3373 err = -EINVAL; 3374 goto out; 3375 } 3376 table->resource_id = resource_id; 3377 table->resource_units = resource_units; 3378 table->resource_valid = true; 3379out: 3380 mutex_unlock(&devlink->lock); 3381 return err; 3382} 3383EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 3384 3385/** 3386 * devlink_resource_occ_get_register - register occupancy getter 3387 * 3388 * @devlink: devlink 3389 * @resource_id: resource id 3390 * @occ_get: occupancy getter callback 3391 * @occ_get_priv: occupancy getter callback priv 3392 */ 3393void devlink_resource_occ_get_register(struct devlink *devlink, 3394 u64 resource_id, 3395 devlink_resource_occ_get_t *occ_get, 3396 void *occ_get_priv) 3397{ 3398 struct devlink_resource *resource; 3399 3400 mutex_lock(&devlink->lock); 3401 resource = devlink_resource_find(devlink, NULL, resource_id); 3402 if (WARN_ON(!resource)) 3403 goto out; 3404 WARN_ON(resource->occ_get); 3405 3406 resource->occ_get = occ_get; 3407 resource->occ_get_priv = occ_get_priv; 3408out: 3409 mutex_unlock(&devlink->lock); 3410} 3411EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 3412 3413/** 3414 * devlink_resource_occ_get_unregister - unregister occupancy getter 3415 * 3416 * @devlink: devlink 3417 * @resource_id: resource id 3418 */ 3419void devlink_resource_occ_get_unregister(struct devlink *devlink, 3420 u64 resource_id) 3421{ 3422 struct devlink_resource *resource; 3423 3424 mutex_lock(&devlink->lock); 3425 resource = devlink_resource_find(devlink, NULL, resource_id); 3426 if (WARN_ON(!resource)) 3427 goto out; 3428 WARN_ON(!resource->occ_get); 3429 3430 resource->occ_get = NULL; 3431 resource->occ_get_priv = NULL; 3432out: 3433 mutex_unlock(&devlink->lock); 3434} 3435EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 3436 3437static int __init devlink_module_init(void) 3438{ 3439 return genl_register_family(&devlink_nl_family); 3440} 3441 3442static void __exit devlink_module_exit(void) 3443{ 3444 genl_unregister_family(&devlink_nl_family); 3445} 3446 3447module_init(devlink_module_init); 3448module_exit(devlink_module_exit); 3449 3450MODULE_LICENSE("GPL v2"); 3451MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 3452MODULE_DESCRIPTION("Network physical device Netlink interface"); 3453MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);