Message ID | 272fa19f57de2d14e9666b4cd9b1ae8a61a94807.1674234430.git.lorenzo@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | xdp: introduce xdp-feature support | expand |
On Fri, Jan 20, 2023 at 9:17 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote: > + > +#define NETDEV_XDP_ACT_BASIC (NETDEV_XDP_ACT_DROP | \ > + NETDEV_XDP_ACT_PASS | \ > + NETDEV_XDP_ACT_TX | \ > + NETDEV_XDP_ACT_ABORTED) Why split it into 4? Is there a driver that does a subset?
On Fri, 20 Jan 2023 18:16:50 +0100 Lorenzo Bianconi wrote: > From: Jakub Kicinski <kuba@kernel.org> > > Add a Netlink spec-compatible family for netdevs. > This is a very simple implementation without much > thought going into it. > > It allows us to reap all the benefits of Netlink specs, > one can use the generic client to issue the commands: > > $ ./gen.py --spec netdev.yaml --do dev_get --json='{"ifindex": 2}' > {'ifindex': 2, 'xdp-features': 31} > > $ ./gen.py --spec netdev.yaml --dump dev_get > [{'ifindex': 1, 'xdp-features': 0}, {'ifindex': 2, 'xdp-features': 31}] In the meantime I added support for rendering enums in Python. So you can show names in the example. eg: $ ./cli.py --spec netdev.yaml --dump dev_get [{'ifindex': 1, 'xdp-features': set()}, {'ifindex': 2, 'xdp-features': {'ndo-xmit', 'pass', 'redirect', 'aborted', 'drop'}}, {'ifindex': 3, 'xdp-features': {'rx-sg'}}] > the generic python library does not have flags-by-name > support, yet, but we also don't have to carry strings > in the messages, as user space can get the names from > the spec. > > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> > Co-developed-by: Marek Majtyka <alardam@gmail.com> > Signed-off-by: Marek Majtyka <alardam@gmail.com> > Signed-off-by: Jakub Kicinski <kuba@kernel.org> > --- > Documentation/netlink/specs/netdev.yaml | 72 ++++++++++ FWIW I'm not 100% sure if we should scope the family to all of netdev or just xdp. Same for the name of the op, should we call the op dev_get or dev_xdp_get.. > diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h > new file mode 100644 > index 000000000000..254fc336d469 > --- /dev/null > +++ b/include/uapi/linux/netdev.h > @@ -0,0 +1,66 @@ > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > +/* Do not edit directly, auto-generated from: */ Like this line says, you can't hand edit this file. Next time someone adds an attribute all your changes will be wiped. > +/* Documentation/netlink/specs/netdev.yaml */ > +/* YNL-GEN uapi header */ > + > +#ifndef _UAPI_LINUX_NETDEV_H > +#define _UAPI_LINUX_NETDEV_H > + > +#define NETDEV_FAMILY_NAME "netdev" > +#define NETDEV_FAMILY_VERSION 1 > + > +enum netdev_xdp_act { > + NETDEV_XDP_ACT_ABORTED_BIT, > + NETDEV_XDP_ACT_DROP_BIT, > + NETDEV_XDP_ACT_PASS_BIT, > + NETDEV_XDP_ACT_TX_BIT, > + NETDEV_XDP_ACT_REDIRECT_BIT, > + NETDEV_XDP_ACT_NDO_XMIT_BIT, > + NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT, > + NETDEV_XDP_ACT_HW_OFFLOAD_BIT, > + NETDEV_XDP_ACT_RX_SG_BIT, > + NETDEV_XDP_ACT_NDO_XMIT_SG_BIT You need to add -bit to all the enum names in the yaml if you want to have _BIT in the name here. > +}; > + > +#define NETDEV_XDP_ACT_ABORTED BIT(NETDEV_XDP_ACT_ABORTED_BIT) > +#define NETDEV_XDP_ACT_DROP BIT(NETDEV_XDP_ACT_DROP_BIT) > +#define NETDEV_XDP_ACT_PASS BIT(NETDEV_XDP_ACT_PASS_BIT) > +#define NETDEV_XDP_ACT_TX BIT(NETDEV_XDP_ACT_TX_BIT) > +#define NETDEV_XDP_ACT_REDIRECT BIT(NETDEV_XDP_ACT_REDIRECT_BIT) > +#define NETDEV_XDP_ACT_NDO_XMIT BIT(NETDEV_XDP_ACT_NDO_XMIT_BIT) > +#define NETDEV_XDP_ACT_XSK_ZEROCOPY BIT(NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT) > +#define NETDEV_XDP_ACT_HW_OFFLOAD BIT(NETDEV_XDP_ACT_HW_OFFLOAD_BIT) > +#define NETDEV_XDP_ACT_RX_SG BIT(NETDEV_XDP_ACT_RX_SG_BIT) > +#define NETDEV_XDP_ACT_NDO_XMIT_SG BIT(NETDEV_XDP_ACT_NDO_XMIT_SG_BIT) > + > +#define NETDEV_XDP_ACT_BASIC (NETDEV_XDP_ACT_DROP | \ > + NETDEV_XDP_ACT_PASS | \ > + NETDEV_XDP_ACT_TX | \ > + NETDEV_XDP_ACT_ABORTED) > +#define NETDEV_XDP_ACT_FULL (NETDEV_XDP_ACT_BASIC | \ > + NETDEV_XDP_ACT_REDIRECT) > +#define NETDEV_XDP_ACT_ZC (NETDEV_XDP_ACT_FULL | \ > + NETDEV_XDP_ACT_XSK_ZEROCOPY) These defines don't belong in uAPI. Especially the use of BIT(). > + if (err < 0) > + break; > +cont: > + idx++; > + } > + } > + > + rtnl_unlock(); > + > + if (err != -EMSGSIZE) > + return err; > + > + cb->args[1] = idx; > + cb->args[0] = h; > + cb->seq = net->dev_base_seq; > + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); I think that this line can be dropped. > + return skb->len; > +}
Hi Lorenzo, I love your patch! Perhaps something to improve: [auto build test WARNING on bpf-next/master] url: https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Bianconi/netdev-genl-create-a-simple-family-for-netdev-stuff/20230121-011957 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master patch link: https://lore.kernel.org/r/272fa19f57de2d14e9666b4cd9b1ae8a61a94807.1674234430.git.lorenzo%40kernel.org patch subject: [PATCH bpf-next 1/7] netdev-genl: create a simple family for netdev stuff config: x86_64-rhel-8.3-syz (https://download.01.org/0day-ci/archive/20230121/202301211259.eI8T3TMB-lkp@intel.com/config) compiler: gcc-11 (Debian 11.3.0-8) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/bab8ed890888146e07283e2ae27174b3562b6931 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Lorenzo-Bianconi/netdev-genl-create-a-simple-family-for-netdev-stuff/20230121-011957 git checkout bab8ed890888146e07283e2ae27174b3562b6931 # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 olddefconfig make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash net/core/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): net/core/netdev-genl.c: In function 'netdev_nl_dev_fill': >> net/core/netdev-genl.c:16:13: warning: unused variable 'err' [-Wunused-variable] 16 | int err; | ^~~ vim +/err +16 net/core/netdev-genl.c 10 11 static int 12 netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp, 13 u32 portid, u32 seq, int flags, u32 cmd) 14 { 15 void *hdr; > 16 int err; 17 18 hdr = genlmsg_put(rsp, portid, seq, &netdev_nl_family, flags, cmd); 19 if (!hdr) 20 return -EMSGSIZE; 21 22 if (nla_put_u32(rsp, NETDEV_A_DEV_IFINDEX, netdev->ifindex) || 23 nla_put_u64_64bit(rsp, NETDEV_A_DEV_XDP_FEATURES, 24 netdev->xdp_features, NETDEV_A_DEV_PAD)) { 25 genlmsg_cancel(rsp, hdr); 26 return -EINVAL; 27 } 28 29 genlmsg_end(rsp, hdr); 30 31 return 0; 32 } 33
On Jan 20, Alexei Starovoitov wrote: > On Fri, Jan 20, 2023 at 9:17 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote: > > + > > +#define NETDEV_XDP_ACT_BASIC (NETDEV_XDP_ACT_DROP | \ > > + NETDEV_XDP_ACT_PASS | \ > > + NETDEV_XDP_ACT_TX | \ > > + NETDEV_XDP_ACT_ABORTED) > > Why split it into 4? > Is there a driver that does a subset? nope, at least all drivers support NETDEV_XDP_ACT_BASIC. I guess we can squash them and just add NETDEV_XDP_ACT_BASIC. Regards, Lorenzo
> On Fri, 20 Jan 2023 18:16:50 +0100 Lorenzo Bianconi wrote: > > From: Jakub Kicinski <kuba@kernel.org> > > > > Add a Netlink spec-compatible family for netdevs. > > This is a very simple implementation without much > > thought going into it. > > > > It allows us to reap all the benefits of Netlink specs, > > one can use the generic client to issue the commands: > > > > $ ./gen.py --spec netdev.yaml --do dev_get --json='{"ifindex": 2}' > > {'ifindex': 2, 'xdp-features': 31} > > > > $ ./gen.py --spec netdev.yaml --dump dev_get > > [{'ifindex': 1, 'xdp-features': 0}, {'ifindex': 2, 'xdp-features': 31}] > > In the meantime I added support for rendering enums in Python. > So you can show names in the example. eg: > > $ ./cli.py --spec netdev.yaml --dump dev_get > [{'ifindex': 1, 'xdp-features': set()}, > {'ifindex': 2, > 'xdp-features': {'ndo-xmit', 'pass', 'redirect', 'aborted', 'drop'}}, > {'ifindex': 3, 'xdp-features': {'rx-sg'}}] > > > the generic python library does not have flags-by-name > > support, yet, but we also don't have to carry strings > > in the messages, as user space can get the names from > > the spec. > > > > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> > > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> > > Co-developed-by: Marek Majtyka <alardam@gmail.com> > > Signed-off-by: Marek Majtyka <alardam@gmail.com> > > Signed-off-by: Jakub Kicinski <kuba@kernel.org> > > --- > > Documentation/netlink/specs/netdev.yaml | 72 ++++++++++ > > FWIW I'm not 100% sure if we should scope the family to all of netdev > or just xdp. Same for the name of the op, should we call the op dev_get > or dev_xdp_get.. is it likely we are going to add non-xdp info here in the near future? If not I would say we can target just xdp for the moment. > > > diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h > > new file mode 100644 > > index 000000000000..254fc336d469 > > --- /dev/null > > +++ b/include/uapi/linux/netdev.h > > @@ -0,0 +1,66 @@ > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > > +/* Do not edit directly, auto-generated from: */ > > Like this line says, you can't hand edit this file. > Next time someone adds an attribute all your changes will be wiped. ack, right. > > > +/* Documentation/netlink/specs/netdev.yaml */ > > +/* YNL-GEN uapi header */ > > + > > +#ifndef _UAPI_LINUX_NETDEV_H > > +#define _UAPI_LINUX_NETDEV_H > > + > > +#define NETDEV_FAMILY_NAME "netdev" > > +#define NETDEV_FAMILY_VERSION 1 > > + > > +enum netdev_xdp_act { > > + NETDEV_XDP_ACT_ABORTED_BIT, > > + NETDEV_XDP_ACT_DROP_BIT, > > + NETDEV_XDP_ACT_PASS_BIT, > > + NETDEV_XDP_ACT_TX_BIT, > > + NETDEV_XDP_ACT_REDIRECT_BIT, > > + NETDEV_XDP_ACT_NDO_XMIT_BIT, > > + NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT, > > + NETDEV_XDP_ACT_HW_OFFLOAD_BIT, > > + NETDEV_XDP_ACT_RX_SG_BIT, > > + NETDEV_XDP_ACT_NDO_XMIT_SG_BIT > > You need to add -bit to all the enum names in the yaml if you want > to have _BIT in the name here. ack, I do not think it is needed (according to the comment below). > > > +}; > > + > > +#define NETDEV_XDP_ACT_ABORTED BIT(NETDEV_XDP_ACT_ABORTED_BIT) > > +#define NETDEV_XDP_ACT_DROP BIT(NETDEV_XDP_ACT_DROP_BIT) > > +#define NETDEV_XDP_ACT_PASS BIT(NETDEV_XDP_ACT_PASS_BIT) > > +#define NETDEV_XDP_ACT_TX BIT(NETDEV_XDP_ACT_TX_BIT) > > +#define NETDEV_XDP_ACT_REDIRECT BIT(NETDEV_XDP_ACT_REDIRECT_BIT) > > +#define NETDEV_XDP_ACT_NDO_XMIT BIT(NETDEV_XDP_ACT_NDO_XMIT_BIT) > > +#define NETDEV_XDP_ACT_XSK_ZEROCOPY BIT(NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT) > > +#define NETDEV_XDP_ACT_HW_OFFLOAD BIT(NETDEV_XDP_ACT_HW_OFFLOAD_BIT) > > +#define NETDEV_XDP_ACT_RX_SG BIT(NETDEV_XDP_ACT_RX_SG_BIT) > > +#define NETDEV_XDP_ACT_NDO_XMIT_SG BIT(NETDEV_XDP_ACT_NDO_XMIT_SG_BIT) > > + > > +#define NETDEV_XDP_ACT_BASIC (NETDEV_XDP_ACT_DROP | \ > > + NETDEV_XDP_ACT_PASS | \ > > + NETDEV_XDP_ACT_TX | \ > > + NETDEV_XDP_ACT_ABORTED) > > +#define NETDEV_XDP_ACT_FULL (NETDEV_XDP_ACT_BASIC | \ > > + NETDEV_XDP_ACT_REDIRECT) > > +#define NETDEV_XDP_ACT_ZC (NETDEV_XDP_ACT_FULL | \ > > + NETDEV_XDP_ACT_XSK_ZEROCOPY) > > These defines don't belong in uAPI. Especially the use of BIT(). since netdev xdp_features is a bitmask, can we use 'flags' as type for definitions in netdev.yaml so we can get rid of this BIT() definitions for both user and kernel space? > > > + if (err < 0) > > + break; > > +cont: > > + idx++; > > + } > > + } > > + > > + rtnl_unlock(); > > + > > + if (err != -EMSGSIZE) > > + return err; > > + > > + cb->args[1] = idx; > > + cb->args[0] = h; > > + cb->seq = net->dev_base_seq; > > + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); > > I think that this line can be dropped. ack, I will fix it. Regards, Lorenzo > > > + return skb->len; > > +}
On Mon, 23 Jan 2023 00:00:15 +0100 Lorenzo Bianconi wrote: > > FWIW I'm not 100% sure if we should scope the family to all of netdev > > or just xdp. Same for the name of the op, should we call the op dev_get > > or dev_xdp_get.. > > is it likely we are going to add non-xdp info here in the near future? If not > I would say we can target just xdp for the moment. What brought it to mind for me was offloads like the NVMe/DDP for instance. Whether that stuff should live in ethtool or a netdev family is a bit unclear. > > These defines don't belong in uAPI. Especially the use of BIT(). > > since netdev xdp_features is a bitmask, can we use 'flags' as type for definitions in > netdev.yaml so we can get rid of this BIT() definitions for both user and > kernel space? If you have no use for the bit numbers - definitely.
> On Mon, 23 Jan 2023 00:00:15 +0100 Lorenzo Bianconi wrote: > > > FWIW I'm not 100% sure if we should scope the family to all of netdev > > > or just xdp. Same for the name of the op, should we call the op dev_get > > > or dev_xdp_get.. > > > > is it likely we are going to add non-xdp info here in the near future? If not > > I would say we can target just xdp for the moment. > > What brought it to mind for me was offloads like the NVMe/DDP for > instance. Whether that stuff should live in ethtool or a netdev > family is a bit unclear. ack, let's keep netdev in this case. > > > > These defines don't belong in uAPI. Especially the use of BIT(). > > > > since netdev xdp_features is a bitmask, can we use 'flags' as type for definitions in > > netdev.yaml so we can get rid of this BIT() definitions for both user and > > kernel space? > > If you have no use for the bit numbers - definitely. ack Regards, Lorenzo
diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml new file mode 100644 index 000000000000..6445fa5af9d3 --- /dev/null +++ b/Documentation/netlink/specs/netdev.yaml @@ -0,0 +1,72 @@ +name: netdev + +doc: + netdev configuration over generic netlink. + +definitions: + - + type: enum + name: xdp-feat + entries: [ aborted, drop, pass, redirect, + ndo-xmit, xsk-zerocopy, + hw-offload, rx-sg, ndo-xmit-sg + ] + +attribute-sets: + - + name: dev + attributes: + - + name: ifindex + doc: netdev ifindex + type: u32 + value: 1 + checks: + min: 1 + - + name: pad + type: pad + - + name: xdp-features + doc: Bitmask of enabled xdp-features. + type: u64 + enum: xdp-feat + enum-as-flags: true + +operations: + list: + - + name: dev-get + doc: Get / dump information about a netdev. + value: 1 + attribute-set: dev + do: + request: + attributes: + - ifindex + reply: &dev-all + attributes: + - ifindex + - xdp-features + dump: + reply: *dev-all + - + name: dev-add-ntf + doc: Notification about device appearing. + notify: dev-get + mcgrp: mgmt + - + name: dev-del-ntf + doc: Notification about device disappearing. + notify: dev-get + mcgrp: mgmt + - + name: dev-change-ntf + doc: Notification about device configuration being changed. + notify: dev-get + mcgrp: mgmt + +mcast-groups: + list: + - + name: mgmt diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index aad12a179e54..5c2ebc214583 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -47,6 +47,7 @@ #include <uapi/linux/netdevice.h> #include <uapi/linux/if_bonding.h> #include <uapi/linux/pkt_cls.h> +#include <uapi/linux/netdev.h> #include <linux/hashtable.h> #include <linux/rbtree.h> #include <net/net_trackers.h> @@ -2048,6 +2049,7 @@ struct net_device { /* Read-mostly cache-line for fast-path access */ unsigned int flags; + xdp_features_t xdp_features; unsigned long long priv_flags; const struct net_device_ops *netdev_ops; int ifindex; diff --git a/include/net/xdp.h b/include/net/xdp.h index 55dbc68bfffc..3d37460f0bdb 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -7,6 +7,7 @@ #define __LINUX_NET_XDP_H__ #include <linux/skbuff.h> /* skb_shared_info */ +#include <uapi/linux/netdev.h> /** * DOC: XDP RX-queue information @@ -43,6 +44,8 @@ enum xdp_mem_type { MEM_TYPE_MAX, }; +typedef u32 xdp_features_t; + /* XDP flags for ndo_xdp_xmit */ #define XDP_XMIT_FLUSH (1U << 0) /* doorbell signal consumer */ #define XDP_XMIT_FLAGS_MASK XDP_XMIT_FLUSH diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h new file mode 100644 index 000000000000..254fc336d469 --- /dev/null +++ b/include/uapi/linux/netdev.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/netdev.yaml */ +/* YNL-GEN uapi header */ + +#ifndef _UAPI_LINUX_NETDEV_H +#define _UAPI_LINUX_NETDEV_H + +#define NETDEV_FAMILY_NAME "netdev" +#define NETDEV_FAMILY_VERSION 1 + +enum netdev_xdp_act { + NETDEV_XDP_ACT_ABORTED_BIT, + NETDEV_XDP_ACT_DROP_BIT, + NETDEV_XDP_ACT_PASS_BIT, + NETDEV_XDP_ACT_TX_BIT, + NETDEV_XDP_ACT_REDIRECT_BIT, + NETDEV_XDP_ACT_NDO_XMIT_BIT, + NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT, + NETDEV_XDP_ACT_HW_OFFLOAD_BIT, + NETDEV_XDP_ACT_RX_SG_BIT, + NETDEV_XDP_ACT_NDO_XMIT_SG_BIT +}; + +#define NETDEV_XDP_ACT_ABORTED BIT(NETDEV_XDP_ACT_ABORTED_BIT) +#define NETDEV_XDP_ACT_DROP BIT(NETDEV_XDP_ACT_DROP_BIT) +#define NETDEV_XDP_ACT_PASS BIT(NETDEV_XDP_ACT_PASS_BIT) +#define NETDEV_XDP_ACT_TX BIT(NETDEV_XDP_ACT_TX_BIT) +#define NETDEV_XDP_ACT_REDIRECT BIT(NETDEV_XDP_ACT_REDIRECT_BIT) +#define NETDEV_XDP_ACT_NDO_XMIT BIT(NETDEV_XDP_ACT_NDO_XMIT_BIT) +#define NETDEV_XDP_ACT_XSK_ZEROCOPY BIT(NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT) +#define NETDEV_XDP_ACT_HW_OFFLOAD BIT(NETDEV_XDP_ACT_HW_OFFLOAD_BIT) +#define NETDEV_XDP_ACT_RX_SG BIT(NETDEV_XDP_ACT_RX_SG_BIT) +#define NETDEV_XDP_ACT_NDO_XMIT_SG BIT(NETDEV_XDP_ACT_NDO_XMIT_SG_BIT) + +#define NETDEV_XDP_ACT_BASIC (NETDEV_XDP_ACT_DROP | \ + NETDEV_XDP_ACT_PASS | \ + NETDEV_XDP_ACT_TX | \ + NETDEV_XDP_ACT_ABORTED) +#define NETDEV_XDP_ACT_FULL (NETDEV_XDP_ACT_BASIC | \ + NETDEV_XDP_ACT_REDIRECT) +#define NETDEV_XDP_ACT_ZC (NETDEV_XDP_ACT_FULL | \ + NETDEV_XDP_ACT_XSK_ZEROCOPY) + +enum { + NETDEV_A_DEV_IFINDEX = 1, + NETDEV_A_DEV_PAD, + NETDEV_A_DEV_XDP_FEATURES, + + __NETDEV_A_DEV_MAX, + NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1) +}; + +enum { + NETDEV_CMD_DEV_GET = 1, + NETDEV_CMD_DEV_ADD_NTF, + NETDEV_CMD_DEV_DEL_NTF, + NETDEV_CMD_DEV_CHANGE_NTF, + + __NETDEV_CMD_MAX, + NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1) +}; + +#define NETDEV_MCGRP_MGMT "mgmt" + +#endif /* _UAPI_LINUX_NETDEV_H */ diff --git a/net/core/Makefile b/net/core/Makefile index 10edd66a8a37..8f367813bc68 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -12,7 +12,8 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o obj-y += dev.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ - fib_notifier.o xdp.o flow_offload.o gro.o + fib_notifier.o xdp.o flow_offload.o gro.o \ + netdev-genl.o netdev-genl-gen.o obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o diff --git a/net/core/netdev-genl-gen.c b/net/core/netdev-genl-gen.c new file mode 100644 index 000000000000..affb427c3b89 --- /dev/null +++ b/net/core/netdev-genl-gen.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/netdev.yaml */ +/* YNL-GEN kernel source */ + +#include <net/netlink.h> +#include <net/genetlink.h> + +#include "netdev-genl-gen.h" + +#include <linux/netdev.h> + +// NETDEV_CMD_DEV_GET - do +static const struct nla_policy netdev_dev_get_nl_policy[NETDEV_A_DEV_IFINDEX + 1] = { + [NETDEV_A_DEV_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1), +}; + +// Ops table for netdev +static const struct genl_split_ops netdev_nl_ops[2] = { + { + .cmd = NETDEV_CMD_DEV_GET, + .doit = netdev_nl_dev_get_doit, + .policy = netdev_dev_get_nl_policy, + .maxattr = NETDEV_A_DEV_IFINDEX, + .flags = GENL_CMD_CAP_DO, + }, + { + .cmd = NETDEV_CMD_DEV_GET, + .dumpit = netdev_nl_dev_get_dumpit, + .flags = GENL_CMD_CAP_DUMP, + }, +}; + +static const struct genl_multicast_group netdev_nl_mcgrps[] = { + [NETDEV_NLGRP_MGMT] = { "mgmt", }, +}; + +struct genl_family netdev_nl_family __ro_after_init = { + .name = NETDEV_FAMILY_NAME, + .version = NETDEV_FAMILY_VERSION, + .netnsok = true, + .parallel_ops = true, + .module = THIS_MODULE, + .split_ops = netdev_nl_ops, + .n_split_ops = ARRAY_SIZE(netdev_nl_ops), + .mcgrps = netdev_nl_mcgrps, + .n_mcgrps = ARRAY_SIZE(netdev_nl_mcgrps), +}; diff --git a/net/core/netdev-genl-gen.h b/net/core/netdev-genl-gen.h new file mode 100644 index 000000000000..8bdbe61e9d74 --- /dev/null +++ b/net/core/netdev-genl-gen.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/netdev.yaml */ +/* YNL-GEN kernel header */ + +#ifndef _LINUX_NETDEV_GEN_H +#define _LINUX_NETDEV_GEN_H + +#include <net/netlink.h> +#include <net/genetlink.h> + +#include <linux/netdev.h> + +int netdev_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info); +int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb); + +enum { + NETDEV_NLGRP_MGMT, +}; + +extern struct genl_family netdev_nl_family; + +#endif /* _LINUX_NETDEV_GEN_H */ diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c new file mode 100644 index 000000000000..ad1751adb3c6 --- /dev/null +++ b/net/core/netdev-genl.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/netdevice.h> +#include <linux/notifier.h> +#include <linux/rtnetlink.h> +#include <net/net_namespace.h> +#include <net/sock.h> + +#include "netdev-genl-gen.h" + +static int +netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp, + u32 portid, u32 seq, int flags, u32 cmd) +{ + void *hdr; + int err; + + hdr = genlmsg_put(rsp, portid, seq, &netdev_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_u32(rsp, NETDEV_A_DEV_IFINDEX, netdev->ifindex) || + nla_put_u64_64bit(rsp, NETDEV_A_DEV_XDP_FEATURES, + netdev->xdp_features, NETDEV_A_DEV_PAD)) { + genlmsg_cancel(rsp, hdr); + return -EINVAL; + } + + genlmsg_end(rsp, hdr); + + return 0; +} + +static void +netdev_genl_dev_notify(struct net_device *netdev, int cmd) +{ + struct sk_buff *ntf; + + if (!genl_has_listeners(&netdev_nl_family, dev_net(netdev), + NETDEV_NLGRP_MGMT)) + return; + + ntf = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!ntf) + return; + + if (netdev_nl_dev_fill(netdev, ntf, 0, 0, 0, cmd)) { + nlmsg_free(ntf); + return; + } + + genlmsg_multicast_netns(&netdev_nl_family, dev_net(netdev), ntf, + 0, NETDEV_NLGRP_MGMT, GFP_KERNEL); +} + +int netdev_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device *netdev; + struct sk_buff *rsp; + u32 ifindex; + int err; + + if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_DEV_IFINDEX)) + return -EINVAL; + + ifindex = nla_get_u32(info->attrs[NETDEV_A_DEV_IFINDEX]); + + rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!rsp) + return -ENOMEM; + + rtnl_lock(); + + netdev = __dev_get_by_index(genl_info_net(info), ifindex); + if (netdev) + err = netdev_nl_dev_fill(netdev, rsp, info->snd_portid, + info->snd_seq, 0, info->genlhdr->cmd); + else + err = -ENODEV; + + rtnl_unlock(); + + if (err) + goto err_free_msg; + + return genlmsg_reply(rsp, info); + +err_free_msg: + nlmsg_free(rsp); + return err; +} + +int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct net *net = sock_net(skb->sk); + struct net_device *netdev; + int idx = 0, s_idx; + int h, s_h; + int err; + + s_h = cb->args[0]; + s_idx = cb->args[1]; + + rtnl_lock(); + + for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { + struct hlist_head *head; + + idx = 0; + head = &net->dev_index_head[h]; + hlist_for_each_entry(netdev, head, index_hlist) { + if (idx < s_idx) + goto cont; + err = netdev_nl_dev_fill(netdev, skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, 0, + NETDEV_CMD_DEV_GET); + if (err < 0) + break; +cont: + idx++; + } + } + + rtnl_unlock(); + + if (err != -EMSGSIZE) + return err; + + cb->args[1] = idx; + cb->args[0] = h; + cb->seq = net->dev_base_seq; + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + + return skb->len; +} + +static int netdev_genl_netdevice_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); + + switch (event) { + case NETDEV_REGISTER: + netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_ADD_NTF); + break; + case NETDEV_UNREGISTER: + netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block netdev_genl_nb = { + .notifier_call = netdev_genl_netdevice_event, +}; + +static int __init netdev_genl_init(void) +{ + int err; + + err = register_netdevice_notifier(&netdev_genl_nb); + if (err) + return err; + + err = genl_register_family(&netdev_nl_family); + if (err) + goto err_unreg_ntf; + + return 0; + +err_unreg_ntf: + unregister_netdevice_notifier(&netdev_genl_nb); + return err; +} + +subsys_initcall(netdev_genl_init); diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h new file mode 100644 index 000000000000..254fc336d469 --- /dev/null +++ b/tools/include/uapi/linux/netdev.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/netdev.yaml */ +/* YNL-GEN uapi header */ + +#ifndef _UAPI_LINUX_NETDEV_H +#define _UAPI_LINUX_NETDEV_H + +#define NETDEV_FAMILY_NAME "netdev" +#define NETDEV_FAMILY_VERSION 1 + +enum netdev_xdp_act { + NETDEV_XDP_ACT_ABORTED_BIT, + NETDEV_XDP_ACT_DROP_BIT, + NETDEV_XDP_ACT_PASS_BIT, + NETDEV_XDP_ACT_TX_BIT, + NETDEV_XDP_ACT_REDIRECT_BIT, + NETDEV_XDP_ACT_NDO_XMIT_BIT, + NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT, + NETDEV_XDP_ACT_HW_OFFLOAD_BIT, + NETDEV_XDP_ACT_RX_SG_BIT, + NETDEV_XDP_ACT_NDO_XMIT_SG_BIT +}; + +#define NETDEV_XDP_ACT_ABORTED BIT(NETDEV_XDP_ACT_ABORTED_BIT) +#define NETDEV_XDP_ACT_DROP BIT(NETDEV_XDP_ACT_DROP_BIT) +#define NETDEV_XDP_ACT_PASS BIT(NETDEV_XDP_ACT_PASS_BIT) +#define NETDEV_XDP_ACT_TX BIT(NETDEV_XDP_ACT_TX_BIT) +#define NETDEV_XDP_ACT_REDIRECT BIT(NETDEV_XDP_ACT_REDIRECT_BIT) +#define NETDEV_XDP_ACT_NDO_XMIT BIT(NETDEV_XDP_ACT_NDO_XMIT_BIT) +#define NETDEV_XDP_ACT_XSK_ZEROCOPY BIT(NETDEV_XDP_ACT_XSK_ZEROCOPY_BIT) +#define NETDEV_XDP_ACT_HW_OFFLOAD BIT(NETDEV_XDP_ACT_HW_OFFLOAD_BIT) +#define NETDEV_XDP_ACT_RX_SG BIT(NETDEV_XDP_ACT_RX_SG_BIT) +#define NETDEV_XDP_ACT_NDO_XMIT_SG BIT(NETDEV_XDP_ACT_NDO_XMIT_SG_BIT) + +#define NETDEV_XDP_ACT_BASIC (NETDEV_XDP_ACT_DROP | \ + NETDEV_XDP_ACT_PASS | \ + NETDEV_XDP_ACT_TX | \ + NETDEV_XDP_ACT_ABORTED) +#define NETDEV_XDP_ACT_FULL (NETDEV_XDP_ACT_BASIC | \ + NETDEV_XDP_ACT_REDIRECT) +#define NETDEV_XDP_ACT_ZC (NETDEV_XDP_ACT_FULL | \ + NETDEV_XDP_ACT_XSK_ZEROCOPY) + +enum { + NETDEV_A_DEV_IFINDEX = 1, + NETDEV_A_DEV_PAD, + NETDEV_A_DEV_XDP_FEATURES, + + __NETDEV_A_DEV_MAX, + NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1) +}; + +enum { + NETDEV_CMD_DEV_GET = 1, + NETDEV_CMD_DEV_ADD_NTF, + NETDEV_CMD_DEV_DEL_NTF, + NETDEV_CMD_DEV_CHANGE_NTF, + + __NETDEV_CMD_MAX, + NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1) +}; + +#define NETDEV_MCGRP_MGMT "mgmt" + +#endif /* _UAPI_LINUX_NETDEV_H */