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