Skip to content

Commit

Permalink
Introduce devlink infrastructure
Browse files Browse the repository at this point in the history
Introduce devlink infrastructure for drivers to register and expose to
userspace via generic Netlink interface.

There are two basic objects defined:
devlink - one instance for every "parent device", for example switch ASIC
devlink port - one instance for every physical port of the device.

This initial portion implements basic get/dump of objects to userspace.
Also, port splitter and port type setting is implemented.

Signed-off-by: Jiri Pirko <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jpirko authored and davem330 committed Mar 1, 2016
1 parent bd070e2 commit bfcd3a4
Show file tree
Hide file tree
Showing 6 changed files with 966 additions and 0 deletions.
8 changes: 8 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3499,6 +3499,14 @@ F: include/linux/device-mapper.h
F: include/linux/dm-*.h
F: include/uapi/linux/dm-*.h

DEVLINK
M: Jiri Pirko <[email protected]>
L: [email protected]
S: Supported
F: net/core/devlink.c
F: include/net/devlink.h
F: include/uapi/linux/devlink.h

DIALOG SEMICONDUCTOR DRIVERS
M: Support Opensource <[email protected]>
W: http://www.dialog-semiconductor.com/products
Expand Down
140 changes: 140 additions & 0 deletions include/net/devlink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* include/net/devlink.h - Network physical device Netlink interface
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Jiri Pirko <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _NET_DEVLINK_H_
#define _NET_DEVLINK_H_

#include <linux/device.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <uapi/linux/devlink.h>

struct devlink_ops;

struct devlink {
struct list_head list;
struct list_head port_list;
const struct devlink_ops *ops;
struct device *dev;
possible_net_t _net;
char priv[0] __aligned(NETDEV_ALIGN);
};

struct devlink_port {
struct list_head list;
struct devlink *devlink;
unsigned index;
bool registered;
enum devlink_port_type type;
enum devlink_port_type desired_type;
void *type_dev;
bool split;
u32 split_group;
};

struct devlink_ops {
size_t priv_size;
int (*port_type_set)(struct devlink_port *devlink_port,
enum devlink_port_type port_type);
int (*port_split)(struct devlink *devlink, unsigned int port_index,
unsigned int count);
int (*port_unsplit)(struct devlink *devlink, unsigned int port_index);
};

static inline void *devlink_priv(struct devlink *devlink)
{
BUG_ON(!devlink);
return &devlink->priv;
}

static inline struct devlink *priv_to_devlink(void *priv)
{
BUG_ON(!priv);
return container_of(priv, struct devlink, priv);
}

struct ib_device;

#if IS_ENABLED(CONFIG_NET_DEVLINK)

struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size);
int devlink_register(struct devlink *devlink, struct device *dev);
void devlink_unregister(struct devlink *devlink);
void devlink_free(struct devlink *devlink);
int devlink_port_register(struct devlink *devlink,
struct devlink_port *devlink_port,
unsigned int port_index);
void devlink_port_unregister(struct devlink_port *devlink_port);
void devlink_port_type_eth_set(struct devlink_port *devlink_port,
struct net_device *netdev);
void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev);
void devlink_port_type_clear(struct devlink_port *devlink_port);
void devlink_port_split_set(struct devlink_port *devlink_port,
u32 split_group);

#else

static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
size_t priv_size)
{
return kzalloc(sizeof(struct devlink) + priv_size, GFP_KERNEL);
}

static inline int devlink_register(struct devlink *devlink, struct device *dev)
{
return 0;
}

static inline void devlink_unregister(struct devlink *devlink)
{
}

static inline void devlink_free(struct devlink *devlink)
{
kfree(devlink);
}

static inline int devlink_port_register(struct devlink *devlink,
struct devlink_port *devlink_port,
unsigned int port_index)
{
return 0;
}

static inline void devlink_port_unregister(struct devlink_port *devlink_port)
{
}

static inline void devlink_port_type_eth_set(struct devlink_port *devlink_port,
struct net_device *netdev)
{
}

static inline void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev)
{
}

static inline void devlink_port_type_clear(struct devlink_port *devlink_port)
{
}

static inline void devlink_port_split_set(struct devlink_port *devlink_port,
u32 split_group)
{
}

#endif

#endif /* _NET_DEVLINK_H_ */
72 changes: 72 additions & 0 deletions include/uapi/linux/devlink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* include/uapi/linux/devlink.h - Network physical device Netlink interface
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Jiri Pirko <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#ifndef _UAPI_LINUX_DEVLINK_H_
#define _UAPI_LINUX_DEVLINK_H_

#define DEVLINK_GENL_NAME "devlink"
#define DEVLINK_GENL_VERSION 0x1
#define DEVLINK_GENL_MCGRP_CONFIG_NAME "config"

enum devlink_command {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_CMD_UNSPEC,

DEVLINK_CMD_GET, /* can dump */
DEVLINK_CMD_SET,
DEVLINK_CMD_NEW,
DEVLINK_CMD_DEL,

DEVLINK_CMD_PORT_GET, /* can dump */
DEVLINK_CMD_PORT_SET,
DEVLINK_CMD_PORT_NEW,
DEVLINK_CMD_PORT_DEL,

DEVLINK_CMD_PORT_SPLIT,
DEVLINK_CMD_PORT_UNSPLIT,

/* add new commands above here */

__DEVLINK_CMD_MAX,
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
};

enum devlink_port_type {
DEVLINK_PORT_TYPE_NOTSET,
DEVLINK_PORT_TYPE_AUTO,
DEVLINK_PORT_TYPE_ETH,
DEVLINK_PORT_TYPE_IB,
};

enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC,

/* bus name + dev name together are a handle for devlink entity */
DEVLINK_ATTR_BUS_NAME, /* string */
DEVLINK_ATTR_DEV_NAME, /* string */

DEVLINK_ATTR_PORT_INDEX, /* u32 */
DEVLINK_ATTR_PORT_TYPE, /* u16 */
DEVLINK_ATTR_PORT_DESIRED_TYPE, /* u16 */
DEVLINK_ATTR_PORT_NETDEV_IFINDEX, /* u32 */
DEVLINK_ATTR_PORT_NETDEV_NAME, /* string */
DEVLINK_ATTR_PORT_IBDEV_NAME, /* string */
DEVLINK_ATTR_PORT_SPLIT_COUNT, /* u32 */
DEVLINK_ATTR_PORT_SPLIT_GROUP, /* u32 */

/* add new attributes above here, update the policy in devlink.c */

__DEVLINK_ATTR_MAX,
DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1
};

#endif /* _UAPI_LINUX_DEVLINK_H_ */
7 changes: 7 additions & 0 deletions net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,13 @@ config DST_CACHE
bool "dst cache"
default n

config NET_DEVLINK
tristate "Network physical/parent device Netlink interface"
help
Network physical/parent device Netlink interface provides
infrastructure to support access to physical chip-wide config and
monitoring.

endif # if NET

# Used by archs to tell that they support BPF_JIT
Expand Down
1 change: 1 addition & 0 deletions net/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
obj-$(CONFIG_DST_CACHE) += dst_cache.o
obj-$(CONFIG_NET_DEVLINK) += devlink.o
Loading

0 comments on commit bfcd3a4

Please sign in to comment.