at v4.16-rc6 86 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 goto err_skb_send_alloc; 1802 goto send_done; 1803 } 1804 1805 return genlmsg_reply(skb, info); 1806 1807nla_put_failure: 1808 err = -EMSGSIZE; 1809err_table_put: 1810err_skb_send_alloc: 1811 genlmsg_cancel(skb, hdr); 1812 nlmsg_free(skb); 1813 return err; 1814} 1815 1816static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 1817 struct genl_info *info) 1818{ 1819 struct devlink *devlink = info->user_ptr[0]; 1820 const char *table_name = NULL; 1821 1822 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 1823 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 1824 1825 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 1826 &devlink->dpipe_table_list, 1827 table_name); 1828} 1829 1830static int devlink_dpipe_value_put(struct sk_buff *skb, 1831 struct devlink_dpipe_value *value) 1832{ 1833 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 1834 value->value_size, value->value)) 1835 return -EMSGSIZE; 1836 if (value->mask) 1837 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 1838 value->value_size, value->mask)) 1839 return -EMSGSIZE; 1840 if (value->mapping_valid) 1841 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 1842 value->mapping_value)) 1843 return -EMSGSIZE; 1844 return 0; 1845} 1846 1847static int devlink_dpipe_action_value_put(struct sk_buff *skb, 1848 struct devlink_dpipe_value *value) 1849{ 1850 if (!value->action) 1851 return -EINVAL; 1852 if (devlink_dpipe_action_put(skb, value->action)) 1853 return -EMSGSIZE; 1854 if (devlink_dpipe_value_put(skb, value)) 1855 return -EMSGSIZE; 1856 return 0; 1857} 1858 1859static int devlink_dpipe_action_values_put(struct sk_buff *skb, 1860 struct devlink_dpipe_value *values, 1861 unsigned int values_count) 1862{ 1863 struct nlattr *action_attr; 1864 int i; 1865 int err; 1866 1867 for (i = 0; i < values_count; i++) { 1868 action_attr = nla_nest_start(skb, 1869 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 1870 if (!action_attr) 1871 return -EMSGSIZE; 1872 err = devlink_dpipe_action_value_put(skb, &values[i]); 1873 if (err) 1874 goto err_action_value_put; 1875 nla_nest_end(skb, action_attr); 1876 } 1877 return 0; 1878 1879err_action_value_put: 1880 nla_nest_cancel(skb, action_attr); 1881 return err; 1882} 1883 1884static int devlink_dpipe_match_value_put(struct sk_buff *skb, 1885 struct devlink_dpipe_value *value) 1886{ 1887 if (!value->match) 1888 return -EINVAL; 1889 if (devlink_dpipe_match_put(skb, value->match)) 1890 return -EMSGSIZE; 1891 if (devlink_dpipe_value_put(skb, value)) 1892 return -EMSGSIZE; 1893 return 0; 1894} 1895 1896static int devlink_dpipe_match_values_put(struct sk_buff *skb, 1897 struct devlink_dpipe_value *values, 1898 unsigned int values_count) 1899{ 1900 struct nlattr *match_attr; 1901 int i; 1902 int err; 1903 1904 for (i = 0; i < values_count; i++) { 1905 match_attr = nla_nest_start(skb, 1906 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 1907 if (!match_attr) 1908 return -EMSGSIZE; 1909 err = devlink_dpipe_match_value_put(skb, &values[i]); 1910 if (err) 1911 goto err_match_value_put; 1912 nla_nest_end(skb, match_attr); 1913 } 1914 return 0; 1915 1916err_match_value_put: 1917 nla_nest_cancel(skb, match_attr); 1918 return err; 1919} 1920 1921static int devlink_dpipe_entry_put(struct sk_buff *skb, 1922 struct devlink_dpipe_entry *entry) 1923{ 1924 struct nlattr *entry_attr, *matches_attr, *actions_attr; 1925 int err; 1926 1927 entry_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ENTRY); 1928 if (!entry_attr) 1929 return -EMSGSIZE; 1930 1931 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 1932 DEVLINK_ATTR_PAD)) 1933 goto nla_put_failure; 1934 if (entry->counter_valid) 1935 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 1936 entry->counter, DEVLINK_ATTR_PAD)) 1937 goto nla_put_failure; 1938 1939 matches_attr = nla_nest_start(skb, 1940 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 1941 if (!matches_attr) 1942 goto nla_put_failure; 1943 1944 err = devlink_dpipe_match_values_put(skb, entry->match_values, 1945 entry->match_values_count); 1946 if (err) { 1947 nla_nest_cancel(skb, matches_attr); 1948 goto err_match_values_put; 1949 } 1950 nla_nest_end(skb, matches_attr); 1951 1952 actions_attr = nla_nest_start(skb, 1953 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 1954 if (!actions_attr) 1955 goto nla_put_failure; 1956 1957 err = devlink_dpipe_action_values_put(skb, entry->action_values, 1958 entry->action_values_count); 1959 if (err) { 1960 nla_nest_cancel(skb, actions_attr); 1961 goto err_action_values_put; 1962 } 1963 nla_nest_end(skb, actions_attr); 1964 1965 nla_nest_end(skb, entry_attr); 1966 return 0; 1967 1968nla_put_failure: 1969 err = -EMSGSIZE; 1970err_match_values_put: 1971err_action_values_put: 1972 nla_nest_cancel(skb, entry_attr); 1973 return err; 1974} 1975 1976static struct devlink_dpipe_table * 1977devlink_dpipe_table_find(struct list_head *dpipe_tables, 1978 const char *table_name) 1979{ 1980 struct devlink_dpipe_table *table; 1981 1982 list_for_each_entry_rcu(table, dpipe_tables, list) { 1983 if (!strcmp(table->name, table_name)) 1984 return table; 1985 } 1986 return NULL; 1987} 1988 1989int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 1990{ 1991 struct devlink *devlink; 1992 int err; 1993 1994 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 1995 dump_ctx->info); 1996 if (err) 1997 return err; 1998 1999 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 2000 dump_ctx->info->snd_portid, 2001 dump_ctx->info->snd_seq, 2002 &devlink_nl_family, NLM_F_MULTI, 2003 dump_ctx->cmd); 2004 if (!dump_ctx->hdr) 2005 goto nla_put_failure; 2006 2007 devlink = dump_ctx->info->user_ptr[0]; 2008 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2009 goto nla_put_failure; 2010 dump_ctx->nest = nla_nest_start(dump_ctx->skb, 2011 DEVLINK_ATTR_DPIPE_ENTRIES); 2012 if (!dump_ctx->nest) 2013 goto nla_put_failure; 2014 return 0; 2015 2016nla_put_failure: 2017 genlmsg_cancel(dump_ctx->skb, dump_ctx->hdr); 2018 nlmsg_free(dump_ctx->skb); 2019 return -EMSGSIZE; 2020} 2021EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2022 2023int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2024 struct devlink_dpipe_entry *entry) 2025{ 2026 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2027} 2028EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2029 2030int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2031{ 2032 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2033 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2034 return 0; 2035} 2036EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2037 2038void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2039 2040{ 2041 unsigned int value_count, value_index; 2042 struct devlink_dpipe_value *value; 2043 2044 value = entry->action_values; 2045 value_count = entry->action_values_count; 2046 for (value_index = 0; value_index < value_count; value_index++) { 2047 kfree(value[value_index].value); 2048 kfree(value[value_index].mask); 2049 } 2050 2051 value = entry->match_values; 2052 value_count = entry->match_values_count; 2053 for (value_index = 0; value_index < value_count; value_index++) { 2054 kfree(value[value_index].value); 2055 kfree(value[value_index].mask); 2056 } 2057} 2058EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2059 2060static int devlink_dpipe_entries_fill(struct genl_info *info, 2061 enum devlink_command cmd, int flags, 2062 struct devlink_dpipe_table *table) 2063{ 2064 struct devlink_dpipe_dump_ctx dump_ctx; 2065 struct nlmsghdr *nlh; 2066 int err; 2067 2068 dump_ctx.skb = NULL; 2069 dump_ctx.cmd = cmd; 2070 dump_ctx.info = info; 2071 2072 err = table->table_ops->entries_dump(table->priv, 2073 table->counters_enabled, 2074 &dump_ctx); 2075 if (err) 2076 goto err_entries_dump; 2077 2078send_done: 2079 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2080 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2081 if (!nlh) { 2082 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2083 if (err) 2084 goto err_skb_send_alloc; 2085 goto send_done; 2086 } 2087 return genlmsg_reply(dump_ctx.skb, info); 2088 2089err_entries_dump: 2090err_skb_send_alloc: 2091 genlmsg_cancel(dump_ctx.skb, dump_ctx.hdr); 2092 nlmsg_free(dump_ctx.skb); 2093 return err; 2094} 2095 2096static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2097 struct genl_info *info) 2098{ 2099 struct devlink *devlink = info->user_ptr[0]; 2100 struct devlink_dpipe_table *table; 2101 const char *table_name; 2102 2103 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2104 return -EINVAL; 2105 2106 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2107 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2108 table_name); 2109 if (!table) 2110 return -EINVAL; 2111 2112 if (!table->table_ops->entries_dump) 2113 return -EINVAL; 2114 2115 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2116 0, table); 2117} 2118 2119static int devlink_dpipe_fields_put(struct sk_buff *skb, 2120 const struct devlink_dpipe_header *header) 2121{ 2122 struct devlink_dpipe_field *field; 2123 struct nlattr *field_attr; 2124 int i; 2125 2126 for (i = 0; i < header->fields_count; i++) { 2127 field = &header->fields[i]; 2128 field_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_FIELD); 2129 if (!field_attr) 2130 return -EMSGSIZE; 2131 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2132 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2133 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2134 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2135 goto nla_put_failure; 2136 nla_nest_end(skb, field_attr); 2137 } 2138 return 0; 2139 2140nla_put_failure: 2141 nla_nest_cancel(skb, field_attr); 2142 return -EMSGSIZE; 2143} 2144 2145static int devlink_dpipe_header_put(struct sk_buff *skb, 2146 struct devlink_dpipe_header *header) 2147{ 2148 struct nlattr *fields_attr, *header_attr; 2149 int err; 2150 2151 header_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER); 2152 if (!header_attr) 2153 return -EMSGSIZE; 2154 2155 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2156 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2157 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2158 goto nla_put_failure; 2159 2160 fields_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2161 if (!fields_attr) 2162 goto nla_put_failure; 2163 2164 err = devlink_dpipe_fields_put(skb, header); 2165 if (err) { 2166 nla_nest_cancel(skb, fields_attr); 2167 goto nla_put_failure; 2168 } 2169 nla_nest_end(skb, fields_attr); 2170 nla_nest_end(skb, header_attr); 2171 return 0; 2172 2173nla_put_failure: 2174 err = -EMSGSIZE; 2175 nla_nest_cancel(skb, header_attr); 2176 return err; 2177} 2178 2179static int devlink_dpipe_headers_fill(struct genl_info *info, 2180 enum devlink_command cmd, int flags, 2181 struct devlink_dpipe_headers * 2182 dpipe_headers) 2183{ 2184 struct devlink *devlink = info->user_ptr[0]; 2185 struct nlattr *headers_attr; 2186 struct sk_buff *skb = NULL; 2187 struct nlmsghdr *nlh; 2188 void *hdr; 2189 int i, j; 2190 int err; 2191 2192 i = 0; 2193start_again: 2194 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2195 if (err) 2196 return err; 2197 2198 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2199 &devlink_nl_family, NLM_F_MULTI, cmd); 2200 if (!hdr) { 2201 nlmsg_free(skb); 2202 return -EMSGSIZE; 2203 } 2204 2205 if (devlink_nl_put_handle(skb, devlink)) 2206 goto nla_put_failure; 2207 headers_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2208 if (!headers_attr) 2209 goto nla_put_failure; 2210 2211 j = 0; 2212 for (; i < dpipe_headers->headers_count; i++) { 2213 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2214 if (err) { 2215 if (!j) 2216 goto err_table_put; 2217 break; 2218 } 2219 j++; 2220 } 2221 nla_nest_end(skb, headers_attr); 2222 genlmsg_end(skb, hdr); 2223 if (i != dpipe_headers->headers_count) 2224 goto start_again; 2225 2226send_done: 2227 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2228 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2229 if (!nlh) { 2230 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2231 if (err) 2232 goto err_skb_send_alloc; 2233 goto send_done; 2234 } 2235 return genlmsg_reply(skb, info); 2236 2237nla_put_failure: 2238 err = -EMSGSIZE; 2239err_table_put: 2240err_skb_send_alloc: 2241 genlmsg_cancel(skb, hdr); 2242 nlmsg_free(skb); 2243 return err; 2244} 2245 2246static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2247 struct genl_info *info) 2248{ 2249 struct devlink *devlink = info->user_ptr[0]; 2250 2251 if (!devlink->dpipe_headers) 2252 return -EOPNOTSUPP; 2253 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2254 0, devlink->dpipe_headers); 2255} 2256 2257static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2258 const char *table_name, 2259 bool enable) 2260{ 2261 struct devlink_dpipe_table *table; 2262 2263 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2264 table_name); 2265 if (!table) 2266 return -EINVAL; 2267 2268 if (table->counter_control_extern) 2269 return -EOPNOTSUPP; 2270 2271 if (!(table->counters_enabled ^ enable)) 2272 return 0; 2273 2274 table->counters_enabled = enable; 2275 if (table->table_ops->counters_set_update) 2276 table->table_ops->counters_set_update(table->priv, enable); 2277 return 0; 2278} 2279 2280static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2281 struct genl_info *info) 2282{ 2283 struct devlink *devlink = info->user_ptr[0]; 2284 const char *table_name; 2285 bool counters_enable; 2286 2287 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2288 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2289 return -EINVAL; 2290 2291 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2292 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2293 2294 return devlink_dpipe_table_counters_set(devlink, table_name, 2295 counters_enable); 2296} 2297 2298static struct devlink_resource * 2299devlink_resource_find(struct devlink *devlink, 2300 struct devlink_resource *resource, u64 resource_id) 2301{ 2302 struct list_head *resource_list; 2303 2304 if (resource) 2305 resource_list = &resource->resource_list; 2306 else 2307 resource_list = &devlink->resource_list; 2308 2309 list_for_each_entry(resource, resource_list, list) { 2310 struct devlink_resource *child_resource; 2311 2312 if (resource->id == resource_id) 2313 return resource; 2314 2315 child_resource = devlink_resource_find(devlink, resource, 2316 resource_id); 2317 if (child_resource) 2318 return child_resource; 2319 } 2320 return NULL; 2321} 2322 2323static void 2324devlink_resource_validate_children(struct devlink_resource *resource) 2325{ 2326 struct devlink_resource *child_resource; 2327 bool size_valid = true; 2328 u64 parts_size = 0; 2329 2330 if (list_empty(&resource->resource_list)) 2331 goto out; 2332 2333 list_for_each_entry(child_resource, &resource->resource_list, list) 2334 parts_size += child_resource->size_new; 2335 2336 if (parts_size > resource->size_new) 2337 size_valid = false; 2338out: 2339 resource->size_valid = size_valid; 2340} 2341 2342static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2343 struct genl_info *info) 2344{ 2345 struct devlink *devlink = info->user_ptr[0]; 2346 struct devlink_resource *resource; 2347 u64 resource_id; 2348 u64 size; 2349 int err; 2350 2351 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2352 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2353 return -EINVAL; 2354 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2355 2356 resource = devlink_resource_find(devlink, NULL, resource_id); 2357 if (!resource) 2358 return -EINVAL; 2359 2360 if (!resource->resource_ops->size_validate) 2361 return -EINVAL; 2362 2363 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2364 err = resource->resource_ops->size_validate(devlink, size, 2365 info->extack); 2366 if (err) 2367 return err; 2368 2369 resource->size_new = size; 2370 devlink_resource_validate_children(resource); 2371 if (resource->parent) 2372 devlink_resource_validate_children(resource->parent); 2373 return 0; 2374} 2375 2376static int 2377devlink_resource_size_params_put(struct devlink_resource *resource, 2378 struct sk_buff *skb) 2379{ 2380 struct devlink_resource_size_params *size_params; 2381 2382 size_params = &resource->size_params; 2383 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2384 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2385 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2386 size_params->size_max, DEVLINK_ATTR_PAD) || 2387 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2388 size_params->size_min, DEVLINK_ATTR_PAD) || 2389 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2390 return -EMSGSIZE; 2391 return 0; 2392} 2393 2394static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2395 struct devlink_resource *resource) 2396{ 2397 struct devlink_resource *child_resource; 2398 struct nlattr *child_resource_attr; 2399 struct nlattr *resource_attr; 2400 2401 resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE); 2402 if (!resource_attr) 2403 return -EMSGSIZE; 2404 2405 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2406 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2407 DEVLINK_ATTR_PAD) || 2408 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2409 DEVLINK_ATTR_PAD)) 2410 goto nla_put_failure; 2411 if (resource->size != resource->size_new) 2412 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2413 resource->size_new, DEVLINK_ATTR_PAD); 2414 if (resource->resource_ops && resource->resource_ops->occ_get) 2415 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2416 resource->resource_ops->occ_get(devlink), 2417 DEVLINK_ATTR_PAD)) 2418 goto nla_put_failure; 2419 if (devlink_resource_size_params_put(resource, skb)) 2420 goto nla_put_failure; 2421 if (list_empty(&resource->resource_list)) 2422 goto out; 2423 2424 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2425 resource->size_valid)) 2426 goto nla_put_failure; 2427 2428 child_resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2429 if (!child_resource_attr) 2430 goto nla_put_failure; 2431 2432 list_for_each_entry(child_resource, &resource->resource_list, list) { 2433 if (devlink_resource_put(devlink, skb, child_resource)) 2434 goto resource_put_failure; 2435 } 2436 2437 nla_nest_end(skb, child_resource_attr); 2438out: 2439 nla_nest_end(skb, resource_attr); 2440 return 0; 2441 2442resource_put_failure: 2443 nla_nest_cancel(skb, child_resource_attr); 2444nla_put_failure: 2445 nla_nest_cancel(skb, resource_attr); 2446 return -EMSGSIZE; 2447} 2448 2449static int devlink_resource_fill(struct genl_info *info, 2450 enum devlink_command cmd, int flags) 2451{ 2452 struct devlink *devlink = info->user_ptr[0]; 2453 struct devlink_resource *resource; 2454 struct nlattr *resources_attr; 2455 struct sk_buff *skb = NULL; 2456 struct nlmsghdr *nlh; 2457 bool incomplete; 2458 void *hdr; 2459 int i; 2460 int err; 2461 2462 resource = list_first_entry(&devlink->resource_list, 2463 struct devlink_resource, list); 2464start_again: 2465 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2466 if (err) 2467 return err; 2468 2469 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2470 &devlink_nl_family, NLM_F_MULTI, cmd); 2471 if (!hdr) { 2472 nlmsg_free(skb); 2473 return -EMSGSIZE; 2474 } 2475 2476 if (devlink_nl_put_handle(skb, devlink)) 2477 goto nla_put_failure; 2478 2479 resources_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2480 if (!resources_attr) 2481 goto nla_put_failure; 2482 2483 incomplete = false; 2484 i = 0; 2485 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2486 err = devlink_resource_put(devlink, skb, resource); 2487 if (err) { 2488 if (!i) 2489 goto err_resource_put; 2490 incomplete = true; 2491 break; 2492 } 2493 i++; 2494 } 2495 nla_nest_end(skb, resources_attr); 2496 genlmsg_end(skb, hdr); 2497 if (incomplete) 2498 goto start_again; 2499send_done: 2500 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2501 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2502 if (!nlh) { 2503 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2504 if (err) 2505 goto err_skb_send_alloc; 2506 goto send_done; 2507 } 2508 return genlmsg_reply(skb, info); 2509 2510nla_put_failure: 2511 err = -EMSGSIZE; 2512err_resource_put: 2513err_skb_send_alloc: 2514 genlmsg_cancel(skb, hdr); 2515 nlmsg_free(skb); 2516 return err; 2517} 2518 2519static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2520 struct genl_info *info) 2521{ 2522 struct devlink *devlink = info->user_ptr[0]; 2523 2524 if (list_empty(&devlink->resource_list)) 2525 return -EOPNOTSUPP; 2526 2527 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2528} 2529 2530static int 2531devlink_resources_validate(struct devlink *devlink, 2532 struct devlink_resource *resource, 2533 struct genl_info *info) 2534{ 2535 struct list_head *resource_list; 2536 int err = 0; 2537 2538 if (resource) 2539 resource_list = &resource->resource_list; 2540 else 2541 resource_list = &devlink->resource_list; 2542 2543 list_for_each_entry(resource, resource_list, list) { 2544 if (!resource->size_valid) 2545 return -EINVAL; 2546 err = devlink_resources_validate(devlink, resource, info); 2547 if (err) 2548 return err; 2549 } 2550 return err; 2551} 2552 2553static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2554{ 2555 struct devlink *devlink = info->user_ptr[0]; 2556 int err; 2557 2558 if (!devlink->ops->reload) 2559 return -EOPNOTSUPP; 2560 2561 err = devlink_resources_validate(devlink, NULL, info); 2562 if (err) { 2563 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2564 return err; 2565 } 2566 return devlink->ops->reload(devlink); 2567} 2568 2569static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 2570 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 2571 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 2572 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 2573 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 2574 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 2575 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 2576 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 2577 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 2578 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 2579 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 2580 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 2581 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 2582 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 2583 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 2584 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 2585 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 2586 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 2587 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 2588 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 2589}; 2590 2591static const struct genl_ops devlink_nl_ops[] = { 2592 { 2593 .cmd = DEVLINK_CMD_GET, 2594 .doit = devlink_nl_cmd_get_doit, 2595 .dumpit = devlink_nl_cmd_get_dumpit, 2596 .policy = devlink_nl_policy, 2597 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2598 /* can be retrieved by unprivileged users */ 2599 }, 2600 { 2601 .cmd = DEVLINK_CMD_PORT_GET, 2602 .doit = devlink_nl_cmd_port_get_doit, 2603 .dumpit = devlink_nl_cmd_port_get_dumpit, 2604 .policy = devlink_nl_policy, 2605 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 2606 /* can be retrieved by unprivileged users */ 2607 }, 2608 { 2609 .cmd = DEVLINK_CMD_PORT_SET, 2610 .doit = devlink_nl_cmd_port_set_doit, 2611 .policy = devlink_nl_policy, 2612 .flags = GENL_ADMIN_PERM, 2613 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 2614 }, 2615 { 2616 .cmd = DEVLINK_CMD_PORT_SPLIT, 2617 .doit = devlink_nl_cmd_port_split_doit, 2618 .policy = devlink_nl_policy, 2619 .flags = GENL_ADMIN_PERM, 2620 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2621 DEVLINK_NL_FLAG_NO_LOCK, 2622 }, 2623 { 2624 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 2625 .doit = devlink_nl_cmd_port_unsplit_doit, 2626 .policy = devlink_nl_policy, 2627 .flags = GENL_ADMIN_PERM, 2628 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2629 DEVLINK_NL_FLAG_NO_LOCK, 2630 }, 2631 { 2632 .cmd = DEVLINK_CMD_SB_GET, 2633 .doit = devlink_nl_cmd_sb_get_doit, 2634 .dumpit = devlink_nl_cmd_sb_get_dumpit, 2635 .policy = devlink_nl_policy, 2636 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2637 DEVLINK_NL_FLAG_NEED_SB, 2638 /* can be retrieved by unprivileged users */ 2639 }, 2640 { 2641 .cmd = DEVLINK_CMD_SB_POOL_GET, 2642 .doit = devlink_nl_cmd_sb_pool_get_doit, 2643 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 2644 .policy = devlink_nl_policy, 2645 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2646 DEVLINK_NL_FLAG_NEED_SB, 2647 /* can be retrieved by unprivileged users */ 2648 }, 2649 { 2650 .cmd = DEVLINK_CMD_SB_POOL_SET, 2651 .doit = devlink_nl_cmd_sb_pool_set_doit, 2652 .policy = devlink_nl_policy, 2653 .flags = GENL_ADMIN_PERM, 2654 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2655 DEVLINK_NL_FLAG_NEED_SB, 2656 }, 2657 { 2658 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 2659 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 2660 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 2661 .policy = devlink_nl_policy, 2662 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2663 DEVLINK_NL_FLAG_NEED_SB, 2664 /* can be retrieved by unprivileged users */ 2665 }, 2666 { 2667 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 2668 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 2669 .policy = devlink_nl_policy, 2670 .flags = GENL_ADMIN_PERM, 2671 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2672 DEVLINK_NL_FLAG_NEED_SB, 2673 }, 2674 { 2675 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 2676 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 2677 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 2678 .policy = devlink_nl_policy, 2679 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2680 DEVLINK_NL_FLAG_NEED_SB, 2681 /* can be retrieved by unprivileged users */ 2682 }, 2683 { 2684 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 2685 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 2686 .policy = devlink_nl_policy, 2687 .flags = GENL_ADMIN_PERM, 2688 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2689 DEVLINK_NL_FLAG_NEED_SB, 2690 }, 2691 { 2692 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 2693 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 2694 .policy = devlink_nl_policy, 2695 .flags = GENL_ADMIN_PERM, 2696 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2697 DEVLINK_NL_FLAG_NEED_SB, 2698 }, 2699 { 2700 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 2701 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 2702 .policy = devlink_nl_policy, 2703 .flags = GENL_ADMIN_PERM, 2704 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2705 DEVLINK_NL_FLAG_NEED_SB, 2706 }, 2707 { 2708 .cmd = DEVLINK_CMD_ESWITCH_GET, 2709 .doit = devlink_nl_cmd_eswitch_get_doit, 2710 .policy = devlink_nl_policy, 2711 .flags = GENL_ADMIN_PERM, 2712 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2713 }, 2714 { 2715 .cmd = DEVLINK_CMD_ESWITCH_SET, 2716 .doit = devlink_nl_cmd_eswitch_set_doit, 2717 .policy = devlink_nl_policy, 2718 .flags = GENL_ADMIN_PERM, 2719 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2720 }, 2721 { 2722 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 2723 .doit = devlink_nl_cmd_dpipe_table_get, 2724 .policy = devlink_nl_policy, 2725 .flags = GENL_ADMIN_PERM, 2726 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2727 }, 2728 { 2729 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 2730 .doit = devlink_nl_cmd_dpipe_entries_get, 2731 .policy = devlink_nl_policy, 2732 .flags = GENL_ADMIN_PERM, 2733 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2734 }, 2735 { 2736 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 2737 .doit = devlink_nl_cmd_dpipe_headers_get, 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_COUNTERS_SET, 2744 .doit = devlink_nl_cmd_dpipe_table_counters_set, 2745 .policy = devlink_nl_policy, 2746 .flags = GENL_ADMIN_PERM, 2747 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2748 }, 2749 { 2750 .cmd = DEVLINK_CMD_RESOURCE_SET, 2751 .doit = devlink_nl_cmd_resource_set, 2752 .policy = devlink_nl_policy, 2753 .flags = GENL_ADMIN_PERM, 2754 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2755 }, 2756 { 2757 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 2758 .doit = devlink_nl_cmd_resource_dump, 2759 .policy = devlink_nl_policy, 2760 .flags = GENL_ADMIN_PERM, 2761 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2762 }, 2763 { 2764 .cmd = DEVLINK_CMD_RELOAD, 2765 .doit = devlink_nl_cmd_reload, 2766 .policy = devlink_nl_policy, 2767 .flags = GENL_ADMIN_PERM, 2768 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2769 DEVLINK_NL_FLAG_NO_LOCK, 2770 }, 2771}; 2772 2773static struct genl_family devlink_nl_family __ro_after_init = { 2774 .name = DEVLINK_GENL_NAME, 2775 .version = DEVLINK_GENL_VERSION, 2776 .maxattr = DEVLINK_ATTR_MAX, 2777 .netnsok = true, 2778 .pre_doit = devlink_nl_pre_doit, 2779 .post_doit = devlink_nl_post_doit, 2780 .module = THIS_MODULE, 2781 .ops = devlink_nl_ops, 2782 .n_ops = ARRAY_SIZE(devlink_nl_ops), 2783 .mcgrps = devlink_nl_mcgrps, 2784 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 2785}; 2786 2787/** 2788 * devlink_alloc - Allocate new devlink instance resources 2789 * 2790 * @ops: ops 2791 * @priv_size: size of user private data 2792 * 2793 * Allocate new devlink instance resources, including devlink index 2794 * and name. 2795 */ 2796struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 2797{ 2798 struct devlink *devlink; 2799 2800 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 2801 if (!devlink) 2802 return NULL; 2803 devlink->ops = ops; 2804 devlink_net_set(devlink, &init_net); 2805 INIT_LIST_HEAD(&devlink->port_list); 2806 INIT_LIST_HEAD(&devlink->sb_list); 2807 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 2808 INIT_LIST_HEAD(&devlink->resource_list); 2809 mutex_init(&devlink->lock); 2810 return devlink; 2811} 2812EXPORT_SYMBOL_GPL(devlink_alloc); 2813 2814/** 2815 * devlink_register - Register devlink instance 2816 * 2817 * @devlink: devlink 2818 */ 2819int devlink_register(struct devlink *devlink, struct device *dev) 2820{ 2821 mutex_lock(&devlink_mutex); 2822 devlink->dev = dev; 2823 list_add_tail(&devlink->list, &devlink_list); 2824 devlink_notify(devlink, DEVLINK_CMD_NEW); 2825 mutex_unlock(&devlink_mutex); 2826 return 0; 2827} 2828EXPORT_SYMBOL_GPL(devlink_register); 2829 2830/** 2831 * devlink_unregister - Unregister devlink instance 2832 * 2833 * @devlink: devlink 2834 */ 2835void devlink_unregister(struct devlink *devlink) 2836{ 2837 mutex_lock(&devlink_mutex); 2838 devlink_notify(devlink, DEVLINK_CMD_DEL); 2839 list_del(&devlink->list); 2840 mutex_unlock(&devlink_mutex); 2841} 2842EXPORT_SYMBOL_GPL(devlink_unregister); 2843 2844/** 2845 * devlink_free - Free devlink instance resources 2846 * 2847 * @devlink: devlink 2848 */ 2849void devlink_free(struct devlink *devlink) 2850{ 2851 kfree(devlink); 2852} 2853EXPORT_SYMBOL_GPL(devlink_free); 2854 2855/** 2856 * devlink_port_register - Register devlink port 2857 * 2858 * @devlink: devlink 2859 * @devlink_port: devlink port 2860 * @port_index 2861 * 2862 * Register devlink port with provided port index. User can use 2863 * any indexing, even hw-related one. devlink_port structure 2864 * is convenient to be embedded inside user driver private structure. 2865 * Note that the caller should take care of zeroing the devlink_port 2866 * structure. 2867 */ 2868int devlink_port_register(struct devlink *devlink, 2869 struct devlink_port *devlink_port, 2870 unsigned int port_index) 2871{ 2872 mutex_lock(&devlink->lock); 2873 if (devlink_port_index_exists(devlink, port_index)) { 2874 mutex_unlock(&devlink->lock); 2875 return -EEXIST; 2876 } 2877 devlink_port->devlink = devlink; 2878 devlink_port->index = port_index; 2879 devlink_port->registered = true; 2880 list_add_tail(&devlink_port->list, &devlink->port_list); 2881 mutex_unlock(&devlink->lock); 2882 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2883 return 0; 2884} 2885EXPORT_SYMBOL_GPL(devlink_port_register); 2886 2887/** 2888 * devlink_port_unregister - Unregister devlink port 2889 * 2890 * @devlink_port: devlink port 2891 */ 2892void devlink_port_unregister(struct devlink_port *devlink_port) 2893{ 2894 struct devlink *devlink = devlink_port->devlink; 2895 2896 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 2897 mutex_lock(&devlink->lock); 2898 list_del(&devlink_port->list); 2899 mutex_unlock(&devlink->lock); 2900} 2901EXPORT_SYMBOL_GPL(devlink_port_unregister); 2902 2903static void __devlink_port_type_set(struct devlink_port *devlink_port, 2904 enum devlink_port_type type, 2905 void *type_dev) 2906{ 2907 devlink_port->type = type; 2908 devlink_port->type_dev = type_dev; 2909 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2910} 2911 2912/** 2913 * devlink_port_type_eth_set - Set port type to Ethernet 2914 * 2915 * @devlink_port: devlink port 2916 * @netdev: related netdevice 2917 */ 2918void devlink_port_type_eth_set(struct devlink_port *devlink_port, 2919 struct net_device *netdev) 2920{ 2921 return __devlink_port_type_set(devlink_port, 2922 DEVLINK_PORT_TYPE_ETH, netdev); 2923} 2924EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 2925 2926/** 2927 * devlink_port_type_ib_set - Set port type to InfiniBand 2928 * 2929 * @devlink_port: devlink port 2930 * @ibdev: related IB device 2931 */ 2932void devlink_port_type_ib_set(struct devlink_port *devlink_port, 2933 struct ib_device *ibdev) 2934{ 2935 return __devlink_port_type_set(devlink_port, 2936 DEVLINK_PORT_TYPE_IB, ibdev); 2937} 2938EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 2939 2940/** 2941 * devlink_port_type_clear - Clear port type 2942 * 2943 * @devlink_port: devlink port 2944 */ 2945void devlink_port_type_clear(struct devlink_port *devlink_port) 2946{ 2947 return __devlink_port_type_set(devlink_port, 2948 DEVLINK_PORT_TYPE_NOTSET, NULL); 2949} 2950EXPORT_SYMBOL_GPL(devlink_port_type_clear); 2951 2952/** 2953 * devlink_port_split_set - Set port is split 2954 * 2955 * @devlink_port: devlink port 2956 * @split_group: split group - identifies group split port is part of 2957 */ 2958void devlink_port_split_set(struct devlink_port *devlink_port, 2959 u32 split_group) 2960{ 2961 devlink_port->split = true; 2962 devlink_port->split_group = split_group; 2963 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2964} 2965EXPORT_SYMBOL_GPL(devlink_port_split_set); 2966 2967int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 2968 u32 size, u16 ingress_pools_count, 2969 u16 egress_pools_count, u16 ingress_tc_count, 2970 u16 egress_tc_count) 2971{ 2972 struct devlink_sb *devlink_sb; 2973 int err = 0; 2974 2975 mutex_lock(&devlink->lock); 2976 if (devlink_sb_index_exists(devlink, sb_index)) { 2977 err = -EEXIST; 2978 goto unlock; 2979 } 2980 2981 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 2982 if (!devlink_sb) { 2983 err = -ENOMEM; 2984 goto unlock; 2985 } 2986 devlink_sb->index = sb_index; 2987 devlink_sb->size = size; 2988 devlink_sb->ingress_pools_count = ingress_pools_count; 2989 devlink_sb->egress_pools_count = egress_pools_count; 2990 devlink_sb->ingress_tc_count = ingress_tc_count; 2991 devlink_sb->egress_tc_count = egress_tc_count; 2992 list_add_tail(&devlink_sb->list, &devlink->sb_list); 2993unlock: 2994 mutex_unlock(&devlink->lock); 2995 return err; 2996} 2997EXPORT_SYMBOL_GPL(devlink_sb_register); 2998 2999void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 3000{ 3001 struct devlink_sb *devlink_sb; 3002 3003 mutex_lock(&devlink->lock); 3004 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 3005 WARN_ON(!devlink_sb); 3006 list_del(&devlink_sb->list); 3007 mutex_unlock(&devlink->lock); 3008 kfree(devlink_sb); 3009} 3010EXPORT_SYMBOL_GPL(devlink_sb_unregister); 3011 3012/** 3013 * devlink_dpipe_headers_register - register dpipe headers 3014 * 3015 * @devlink: devlink 3016 * @dpipe_headers: dpipe header array 3017 * 3018 * Register the headers supported by hardware. 3019 */ 3020int devlink_dpipe_headers_register(struct devlink *devlink, 3021 struct devlink_dpipe_headers *dpipe_headers) 3022{ 3023 mutex_lock(&devlink->lock); 3024 devlink->dpipe_headers = dpipe_headers; 3025 mutex_unlock(&devlink->lock); 3026 return 0; 3027} 3028EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 3029 3030/** 3031 * devlink_dpipe_headers_unregister - unregister dpipe headers 3032 * 3033 * @devlink: devlink 3034 * 3035 * Unregister the headers supported by hardware. 3036 */ 3037void devlink_dpipe_headers_unregister(struct devlink *devlink) 3038{ 3039 mutex_lock(&devlink->lock); 3040 devlink->dpipe_headers = NULL; 3041 mutex_unlock(&devlink->lock); 3042} 3043EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 3044 3045/** 3046 * devlink_dpipe_table_counter_enabled - check if counter allocation 3047 * required 3048 * @devlink: devlink 3049 * @table_name: tables name 3050 * 3051 * Used by driver to check if counter allocation is required. 3052 * After counter allocation is turned on the table entries 3053 * are updated to include counter statistics. 3054 * 3055 * After that point on the driver must respect the counter 3056 * state so that each entry added to the table is added 3057 * with a counter. 3058 */ 3059bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 3060 const char *table_name) 3061{ 3062 struct devlink_dpipe_table *table; 3063 bool enabled; 3064 3065 rcu_read_lock(); 3066 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3067 table_name); 3068 enabled = false; 3069 if (table) 3070 enabled = table->counters_enabled; 3071 rcu_read_unlock(); 3072 return enabled; 3073} 3074EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 3075 3076/** 3077 * devlink_dpipe_table_register - register dpipe table 3078 * 3079 * @devlink: devlink 3080 * @table_name: table name 3081 * @table_ops: table ops 3082 * @priv: priv 3083 * @counter_control_extern: external control for counters 3084 */ 3085int devlink_dpipe_table_register(struct devlink *devlink, 3086 const char *table_name, 3087 struct devlink_dpipe_table_ops *table_ops, 3088 void *priv, bool counter_control_extern) 3089{ 3090 struct devlink_dpipe_table *table; 3091 3092 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 3093 return -EEXIST; 3094 3095 if (WARN_ON(!table_ops->size_get)) 3096 return -EINVAL; 3097 3098 table = kzalloc(sizeof(*table), GFP_KERNEL); 3099 if (!table) 3100 return -ENOMEM; 3101 3102 table->name = table_name; 3103 table->table_ops = table_ops; 3104 table->priv = priv; 3105 table->counter_control_extern = counter_control_extern; 3106 3107 mutex_lock(&devlink->lock); 3108 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 3109 mutex_unlock(&devlink->lock); 3110 return 0; 3111} 3112EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 3113 3114/** 3115 * devlink_dpipe_table_unregister - unregister dpipe table 3116 * 3117 * @devlink: devlink 3118 * @table_name: table name 3119 */ 3120void devlink_dpipe_table_unregister(struct devlink *devlink, 3121 const char *table_name) 3122{ 3123 struct devlink_dpipe_table *table; 3124 3125 mutex_lock(&devlink->lock); 3126 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3127 table_name); 3128 if (!table) 3129 goto unlock; 3130 list_del_rcu(&table->list); 3131 mutex_unlock(&devlink->lock); 3132 kfree_rcu(table, rcu); 3133 return; 3134unlock: 3135 mutex_unlock(&devlink->lock); 3136} 3137EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 3138 3139/** 3140 * devlink_resource_register - devlink resource register 3141 * 3142 * @devlink: devlink 3143 * @resource_name: resource's name 3144 * @top_hierarchy: top hierarchy 3145 * @reload_required: reload is required for new configuration to 3146 * apply 3147 * @resource_size: resource's size 3148 * @resource_id: resource's id 3149 * @parent_reosurce_id: resource's parent id 3150 * @size params: size parameters 3151 * @resource_ops: resource ops 3152 */ 3153int devlink_resource_register(struct devlink *devlink, 3154 const char *resource_name, 3155 bool top_hierarchy, 3156 u64 resource_size, 3157 u64 resource_id, 3158 u64 parent_resource_id, 3159 const struct devlink_resource_size_params *size_params, 3160 const struct devlink_resource_ops *resource_ops) 3161{ 3162 struct devlink_resource *resource; 3163 struct list_head *resource_list; 3164 int err = 0; 3165 3166 mutex_lock(&devlink->lock); 3167 resource = devlink_resource_find(devlink, NULL, resource_id); 3168 if (resource) { 3169 err = -EINVAL; 3170 goto out; 3171 } 3172 3173 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 3174 if (!resource) { 3175 err = -ENOMEM; 3176 goto out; 3177 } 3178 3179 if (top_hierarchy) { 3180 resource_list = &devlink->resource_list; 3181 } else { 3182 struct devlink_resource *parent_resource; 3183 3184 parent_resource = devlink_resource_find(devlink, NULL, 3185 parent_resource_id); 3186 if (parent_resource) { 3187 resource_list = &parent_resource->resource_list; 3188 resource->parent = parent_resource; 3189 } else { 3190 kfree(resource); 3191 err = -EINVAL; 3192 goto out; 3193 } 3194 } 3195 3196 resource->name = resource_name; 3197 resource->size = resource_size; 3198 resource->size_new = resource_size; 3199 resource->id = resource_id; 3200 resource->resource_ops = resource_ops; 3201 resource->size_valid = true; 3202 memcpy(&resource->size_params, size_params, 3203 sizeof(resource->size_params)); 3204 INIT_LIST_HEAD(&resource->resource_list); 3205 list_add_tail(&resource->list, resource_list); 3206out: 3207 mutex_unlock(&devlink->lock); 3208 return err; 3209} 3210EXPORT_SYMBOL_GPL(devlink_resource_register); 3211 3212/** 3213 * devlink_resources_unregister - free all resources 3214 * 3215 * @devlink: devlink 3216 * @resource: resource 3217 */ 3218void devlink_resources_unregister(struct devlink *devlink, 3219 struct devlink_resource *resource) 3220{ 3221 struct devlink_resource *tmp, *child_resource; 3222 struct list_head *resource_list; 3223 3224 if (resource) 3225 resource_list = &resource->resource_list; 3226 else 3227 resource_list = &devlink->resource_list; 3228 3229 if (!resource) 3230 mutex_lock(&devlink->lock); 3231 3232 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 3233 devlink_resources_unregister(devlink, child_resource); 3234 list_del(&child_resource->list); 3235 kfree(child_resource); 3236 } 3237 3238 if (!resource) 3239 mutex_unlock(&devlink->lock); 3240} 3241EXPORT_SYMBOL_GPL(devlink_resources_unregister); 3242 3243/** 3244 * devlink_resource_size_get - get and update size 3245 * 3246 * @devlink: devlink 3247 * @resource_id: the requested resource id 3248 * @p_resource_size: ptr to update 3249 */ 3250int devlink_resource_size_get(struct devlink *devlink, 3251 u64 resource_id, 3252 u64 *p_resource_size) 3253{ 3254 struct devlink_resource *resource; 3255 int err = 0; 3256 3257 mutex_lock(&devlink->lock); 3258 resource = devlink_resource_find(devlink, NULL, resource_id); 3259 if (!resource) { 3260 err = -EINVAL; 3261 goto out; 3262 } 3263 *p_resource_size = resource->size_new; 3264 resource->size = resource->size_new; 3265out: 3266 mutex_unlock(&devlink->lock); 3267 return err; 3268} 3269EXPORT_SYMBOL_GPL(devlink_resource_size_get); 3270 3271/** 3272 * devlink_dpipe_table_resource_set - set the resource id 3273 * 3274 * @devlink: devlink 3275 * @table_name: table name 3276 * @resource_id: resource id 3277 * @resource_units: number of resource's units consumed per table's entry 3278 */ 3279int devlink_dpipe_table_resource_set(struct devlink *devlink, 3280 const char *table_name, u64 resource_id, 3281 u64 resource_units) 3282{ 3283 struct devlink_dpipe_table *table; 3284 int err = 0; 3285 3286 mutex_lock(&devlink->lock); 3287 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3288 table_name); 3289 if (!table) { 3290 err = -EINVAL; 3291 goto out; 3292 } 3293 table->resource_id = resource_id; 3294 table->resource_units = resource_units; 3295 table->resource_valid = true; 3296out: 3297 mutex_unlock(&devlink->lock); 3298 return err; 3299} 3300EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 3301 3302static int __init devlink_module_init(void) 3303{ 3304 return genl_register_family(&devlink_nl_family); 3305} 3306 3307static void __exit devlink_module_exit(void) 3308{ 3309 genl_unregister_family(&devlink_nl_family); 3310} 3311 3312module_init(devlink_module_init); 3313module_exit(devlink_module_exit); 3314 3315MODULE_LICENSE("GPL v2"); 3316MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 3317MODULE_DESCRIPTION("Network physical device Netlink interface"); 3318MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);