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