Skip to content

Commit a1d397d

Browse files
liuhangbingregkh
authored andcommitted
net: add a common function to compute features for upper devices
[ Upstream commit 28098de ] Some high level software drivers need to compute features from lower devices. But each has their own implementations and may lost some feature compute. Let's use one common function to compute features for kinds of these devices. The new helper uses the current bond implementation as the reference one, as the latter already handles all the relevant aspects: netdev features, TSO limits and dst retention. Suggested-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Link: https://patch.msgid.link/20251017034155.61990-2-liuhangbin@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Stable-dep-of: 950803f ("bonding: fix type confusion in bond_setup_by_slave()") Signed-off-by: Wentao Guan <guanwentao@uniontech.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent ed97672 commit a1d397d

3 files changed

Lines changed: 107 additions & 0 deletions

File tree

include/linux/netdev_features.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,24 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
261261
NETIF_F_GSO_UDP_TUNNEL | \
262262
NETIF_F_GSO_UDP_TUNNEL_CSUM)
263263

264+
/* virtual device features */
265+
#define MASTER_UPPER_DEV_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
266+
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
267+
NETIF_F_GSO_ENCAP_ALL | \
268+
NETIF_F_HIGHDMA | NETIF_F_LRO)
269+
270+
#define MASTER_UPPER_DEV_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
271+
NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE | \
272+
NETIF_F_GSO_PARTIAL)
273+
274+
#define MASTER_UPPER_DEV_MPLS_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
275+
NETIF_F_GSO_SOFTWARE)
276+
277+
#define MASTER_UPPER_DEV_XFRM_FEATURES (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM | \
278+
NETIF_F_GSO_ESP)
279+
280+
#define MASTER_UPPER_DEV_GSO_PARTIAL_FEATURES (NETIF_F_GSO_ESP)
281+
264282
static inline netdev_features_t netdev_base_features(netdev_features_t features)
265283
{
266284
features &= ~NETIF_F_ONE_FOR_ALL;

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,6 +5005,7 @@ static inline netdev_features_t netdev_add_tso_features(netdev_features_t featur
50055005
int __netdev_update_features(struct net_device *dev);
50065006
void netdev_update_features(struct net_device *dev);
50075007
void netdev_change_features(struct net_device *dev);
5008+
void netdev_compute_master_upper_features(struct net_device *dev, bool update_header);
50085009

50095010
void netif_stacked_transfer_operstate(const struct net_device *rootdev,
50105011
struct net_device *dev);

net/core/dev.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11450,6 +11450,94 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
1145011450
}
1145111451
EXPORT_SYMBOL(netdev_increment_features);
1145211452

11453+
/**
11454+
* netdev_compute_master_upper_features - compute feature from lowers
11455+
* @dev: the upper device
11456+
* @update_header: whether to update upper device's header_len/headroom/tailroom
11457+
*
11458+
* Recompute the upper device's feature based on all lower devices.
11459+
*/
11460+
void netdev_compute_master_upper_features(struct net_device *dev, bool update_header)
11461+
{
11462+
unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
11463+
netdev_features_t gso_partial_features = MASTER_UPPER_DEV_GSO_PARTIAL_FEATURES;
11464+
netdev_features_t xfrm_features = MASTER_UPPER_DEV_XFRM_FEATURES;
11465+
netdev_features_t mpls_features = MASTER_UPPER_DEV_MPLS_FEATURES;
11466+
netdev_features_t vlan_features = MASTER_UPPER_DEV_VLAN_FEATURES;
11467+
netdev_features_t enc_features = MASTER_UPPER_DEV_ENC_FEATURES;
11468+
unsigned short max_header_len = ETH_HLEN;
11469+
unsigned int tso_max_size = TSO_MAX_SIZE;
11470+
unsigned short max_headroom = 0;
11471+
unsigned short max_tailroom = 0;
11472+
u16 tso_max_segs = TSO_MAX_SEGS;
11473+
struct net_device *lower_dev;
11474+
struct list_head *iter;
11475+
11476+
mpls_features = netdev_base_features(mpls_features);
11477+
vlan_features = netdev_base_features(vlan_features);
11478+
enc_features = netdev_base_features(enc_features);
11479+
11480+
netdev_for_each_lower_dev(dev, lower_dev, iter) {
11481+
gso_partial_features = netdev_increment_features(gso_partial_features,
11482+
lower_dev->gso_partial_features,
11483+
MASTER_UPPER_DEV_GSO_PARTIAL_FEATURES);
11484+
11485+
vlan_features = netdev_increment_features(vlan_features,
11486+
lower_dev->vlan_features,
11487+
MASTER_UPPER_DEV_VLAN_FEATURES);
11488+
11489+
enc_features = netdev_increment_features(enc_features,
11490+
lower_dev->hw_enc_features,
11491+
MASTER_UPPER_DEV_ENC_FEATURES);
11492+
11493+
if (IS_ENABLED(CONFIG_XFRM_OFFLOAD))
11494+
xfrm_features = netdev_increment_features(xfrm_features,
11495+
lower_dev->hw_enc_features,
11496+
MASTER_UPPER_DEV_XFRM_FEATURES);
11497+
11498+
mpls_features = netdev_increment_features(mpls_features,
11499+
lower_dev->mpls_features,
11500+
MASTER_UPPER_DEV_MPLS_FEATURES);
11501+
11502+
dst_release_flag &= lower_dev->priv_flags;
11503+
11504+
if (update_header) {
11505+
max_header_len = max(max_header_len, lower_dev->hard_header_len);
11506+
max_headroom = max(max_headroom, lower_dev->needed_headroom);
11507+
max_tailroom = max(max_tailroom, lower_dev->needed_tailroom);
11508+
}
11509+
11510+
tso_max_size = min(tso_max_size, lower_dev->tso_max_size);
11511+
tso_max_segs = min(tso_max_segs, lower_dev->tso_max_segs);
11512+
}
11513+
11514+
dev->gso_partial_features = gso_partial_features;
11515+
dev->vlan_features = vlan_features;
11516+
dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
11517+
NETIF_F_HW_VLAN_CTAG_TX |
11518+
NETIF_F_HW_VLAN_STAG_TX;
11519+
if (IS_ENABLED(CONFIG_XFRM_OFFLOAD))
11520+
dev->hw_enc_features |= xfrm_features;
11521+
dev->mpls_features = mpls_features;
11522+
11523+
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
11524+
if ((dev->priv_flags & IFF_XMIT_DST_RELEASE_PERM) &&
11525+
dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
11526+
dev->priv_flags |= IFF_XMIT_DST_RELEASE;
11527+
11528+
if (update_header) {
11529+
dev->hard_header_len = max_header_len;
11530+
dev->needed_headroom = max_headroom;
11531+
dev->needed_tailroom = max_tailroom;
11532+
}
11533+
11534+
netif_set_tso_max_segs(dev, tso_max_segs);
11535+
netif_set_tso_max_size(dev, tso_max_size);
11536+
11537+
netdev_change_features(dev);
11538+
}
11539+
EXPORT_SYMBOL(netdev_compute_master_upper_features);
11540+
1145311541
static struct hlist_head * __net_init netdev_create_hash(void)
1145411542
{
1145511543
int i;

0 commit comments

Comments
 (0)