diff mbox series

[bpf-next,1/7] netdev-genl: create a simple family for netdev stuff

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

Checks

Context Check Description
bpf/vmtest-bpf-next-PR fail PR summary
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 4353 this patch: 4354
netdev/cc_maintainers warning 4 maintainers not CCed: imagedong@tencent.com linux-doc@vger.kernel.org john.fastabend@gmail.com corbet@lwn.net
netdev/build_clang fail Errors and warnings before: 1020 this patch: 1022
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 4563 this patch: 4564
netdev/checkpatch warning WARNING: Improper SPDX comment style for 'net/core/netdev-genl-gen.h', please use '/*' instead WARNING: Missing or malformed SPDX-License-Identifier tag in line 1 WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 85 exceeds 80 columns
netdev/kdoc fail Errors and warnings before: 0 this patch: 1
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ${{ matrix.test }} on ${{ matrix.arch }} with ${{ matrix.toolchain }}
bpf/vmtest-bpf-next-VM_Test-2 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-3 fail Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-4 fail Logs for build for aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-5 fail Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-6 fail Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-7 fail Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-8 success Logs for llvm-toolchain
bpf/vmtest-bpf-next-VM_Test-9 success Logs for set-matrix

Commit Message

Lorenzo Bianconi Jan. 20, 2023, 5:16 p.m. UTC
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}]

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 ++++++++++
 include/linux/netdevice.h               |   2 +
 include/net/xdp.h                       |   3 +
 include/uapi/linux/netdev.h             |  66 +++++++++
 net/core/Makefile                       |   3 +-
 net/core/netdev-genl-gen.c              |  48 +++++++
 net/core/netdev-genl-gen.h              |  23 +++
 net/core/netdev-genl.c                  | 178 ++++++++++++++++++++++++
 tools/include/uapi/linux/netdev.h       |  66 +++++++++
 9 files changed, 460 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/netlink/specs/netdev.yaml
 create mode 100644 include/uapi/linux/netdev.h
 create mode 100644 net/core/netdev-genl-gen.c
 create mode 100644 net/core/netdev-genl-gen.h
 create mode 100644 net/core/netdev-genl.c
 create mode 100644 tools/include/uapi/linux/netdev.h

Comments

Alexei Starovoitov Jan. 21, 2023, 1:19 a.m. UTC | #1
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?
Jakub Kicinski Jan. 21, 2023, 3:11 a.m. UTC | #2
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;
> +}
kernel test robot Jan. 21, 2023, 4:42 a.m. UTC | #3
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
Lorenzo Bianconi Jan. 22, 2023, 5:45 p.m. UTC | #4
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
Lorenzo Bianconi Jan. 22, 2023, 11 p.m. UTC | #5
> 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;
> > +}
Jakub Kicinski Jan. 23, 2023, 8:01 p.m. UTC | #6
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.
Lorenzo Bianconi Jan. 23, 2023, 11:29 p.m. UTC | #7
> 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 mbox series

Patch

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 */