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