lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 19 Apr 2022 16:40:45 +0200
From:   Alexander Lobakin <alexandr.lobakin@...el.com>
To:     Jian Shen <shenjian15@...wei.com>
Cc:     Alexander Lobakin <alexandr.lobakin@...el.com>,
        davem@...emloft.net, kuba@...nel.org, andrew@...n.ch,
        ecree.xilinx@...il.com, hkallweit1@...il.com, saeed@...nel.org,
        leon@...nel.org, netdev@...r.kernel.org, linuxarm@...neuler.org,
        lipeng321@...wei.com
Subject: Re: [RFCv6 PATCH net-next 01/19] net: introduce operation helpers for netdev features

From: Jian Shen <shenjian15@...wei.com>
Date: Tue, 19 Apr 2022 10:21:48 +0800

> Introduce a set of bitmap operation helpers for netdev features,
> then we can use them to replace the logical operation with them.
> As the nic driversare not supposed to modify netdev_features
> directly, it also introduces wrappers helpers to this.
> 
> The implementation of these helpers are based on the old prototype
> of netdev_features_t is still u64. I will rewrite them on the last
> patch, when the prototype changes.
> 
> To avoid interdependencies between netdev_features_helper.h and
> netdevice.h, put the helpers for testing feature is set in the
> netdevice.h, and move advandced helpers like
> netdev_get_wanted_features() and netdev_intersect_features() to
> netdev_features_helper.h.
> 
> Signed-off-by: Jian Shen <shenjian15@...wei.com>
> ---
>  .../net/ethernet/netronome/nfp/nfp_net_repr.c |   1 +
>  include/linux/netdev_features.h               |  12 +
>  include/linux/netdev_features_helper.h        | 604 ++++++++++++++++++
>  include/linux/netdevice.h                     |  45 +-
>  net/8021q/vlan_dev.c                          |   1 +
>  net/core/dev.c                                |   1 +
>  6 files changed, 646 insertions(+), 18 deletions(-)
>  create mode 100644 include/linux/netdev_features_helper.h
> 
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> index ba3fa7eac98d..08f2c54e0a11 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> @@ -4,6 +4,7 @@
>  #include <linux/etherdevice.h>
>  #include <linux/io-64-nonatomic-hi-lo.h>
>  #include <linux/lockdep.h>
> +#include <linux/netdev_features_helper.h>
>  #include <net/dst_metadata.h>
>  
>  #include "nfpcore/nfp_cpp.h"
> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
> index 2c6b9e416225..e2b66fa3d7d6 100644
> --- a/include/linux/netdev_features.h
> +++ b/include/linux/netdev_features.h
> @@ -11,6 +11,18 @@
>  
>  typedef u64 netdev_features_t;
>  
> +struct netdev_feature_set {
> +	unsigned int cnt;
> +	unsigned short feature_bits[];
> +};
> +
> +#define DECLARE_NETDEV_FEATURE_SET(name, features...)		\
> +	static unsigned short __##name##_s[] = {features};	\
> +	struct netdev_feature_set name = {			\

I suggest using `const` here. Those sets are needed only to
initialize bitmaps, that's it. They are not supposed to be
modified. This would be one more hardening here to avoid some weird
usages of sets, and also would place them in .rodata instead of just
.data.

Function                                     old     new   delta
main                                          35      33      -2
Total: Before=78, After=76, chg -2.56%
add/remove: 0/2 grow/shrink: 0/0 up/down: 0/-14 (-14)
Data                                         old     new   delta
arr1                                           6       -      -6
arr2                                           8       -      -8
Total: Before=15, After=1, chg -93.33%
add/remove: 2/0 grow/shrink: 0/0 up/down: 14/0 (14)
RO Data                                      old     new   delta
arr1                                           -       8      +8
arr2                                           -       6      +6
Total: Before=36, After=50, chg +38.89%

As you can see, there's a 2-byte code optimization. And that was
just a simpliest oneliner. The gains will be much bigger from the
real usages.

> +		.cnt = ARRAY_SIZE(__##name##_s),		\
> +		.feature_bits = {features},			\
> +	}

The problem with the current macro is that it doesn't allow to
declare feature sets as static. Because the temporary array for
counting the number of bits goes first, and doing

static DECLARE_NETDEV_FEATURE_SET();

wouldn't change anything.
But we want to have most feature sets static as they will be needed
only inside one file. Making every of them global would hurt
optimization.

At the end, I came to

#define DECLARE_NETDEV_FEATURE_SET(name, features...)			\
	const struct netdev_feature_set name = {			\
		.feature_bits = { features },				\
		.cnt = sizeof((u16 []){ features }) / sizeof(u16),	\
	}

because ARRAY_SIZE() can be taken only from a variable, not from
a compound literal.
But this one is actually OK. We don't need ARRAY_SIZE() in here
since we define an unnamed array of an explicit type that we know
for sure inline. So there's no chance to do it wrong as long as
the @features argument is correct.

The ability to make it static is important. For example, when I
marked them both static, I got

add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
Function                                     old     new   delta
Total: Before=76, After=76, chg +0.00%
add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
Data                                         old     new   delta
Total: Before=1, After=1, chg +0.00%
add/remove: 0/2 grow/shrink: 0/0 up/down: 0/-14 (-14)
RO Data                                      old     new   delta
arr1                                           6       -      -6
arr2                                           8       -      -8
Total: Before=50, After=36, chg -28.00%

i.e. both of the sets were removed, because my main() was:

	printf("cnt1: %u, cnt2: %u\n", arr1.cnt, arr2.cnt);

The compiler saw that I don't use them, except for printing values
which are actually compile-time constants, and wiped them.
Previously, they were global so it didn't have a clue if they're
used anywhere else.
This was a simple stupid example, but it will bring a lot more value
in real use cases. So please consider my variant :D

> +
>  enum {
>  	NETIF_F_SG_BIT,			/* Scatter/gather IO. */
>  	NETIF_F_IP_CSUM_BIT,		/* Can checksum TCP/UDP over IPv4. */

--- 8< ---

> -- 
> 2.33.0

Thanks,
Al

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ