@@ -714,14 +714,11 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
return ret;
}
-static inline netdev_features_t
-netdev_get_wanted_features(struct net_device *dev)
+static inline void
+netdev_get_wanted_features(struct net_device *dev, netdev_features_t *wanted)
{
- netdev_features_t tmp;
-
- netdev_features_andnot(tmp, dev->features, dev->hw_features);
- netdev_features_set(tmp, dev->wanted_features);
- return tmp;
+ netdev_features_andnot(*wanted, dev->features, dev->hw_features);
+ netdev_features_set(*wanted, dev->wanted_features);
}
#endif
@@ -4770,7 +4770,7 @@ void netdev_rss_key_fill(void *buffer, size_t len);
int skb_checksum_help(struct sk_buff *skb);
int skb_crc32c_csum_help(struct sk_buff *skb);
int skb_csum_hwoffload_help(struct sk_buff *skb,
- const netdev_features_t features);
+ const netdev_features_t *features);
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
netdev_features_t features, bool tx_path);
@@ -3461,41 +3461,33 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
* instead of standard features for the netdev.
*/
#if IS_ENABLED(CONFIG_NET_MPLS_GSO)
-static netdev_features_t net_mpls_features(struct sk_buff *skb,
- netdev_features_t features,
- __be16 type)
+static void net_mpls_features(struct sk_buff *skb, netdev_features_t *features,
+ __be16 type)
{
if (eth_p_mpls(type))
- netdev_features_mask(features, skb->dev->mpls_features);
-
- return features;
+ netdev_features_mask(*features, skb->dev->mpls_features);
}
#else
-static netdev_features_t net_mpls_features(struct sk_buff *skb,
- netdev_features_t features,
- __be16 type)
+static void net_mpls_features(struct sk_buff *skb, netdev_features_t *features,
+ __be16 type)
{
- return features;
}
#endif
-static netdev_features_t harmonize_features(struct sk_buff *skb,
- netdev_features_t features)
+static void harmonize_features(struct sk_buff *skb, netdev_features_t *features)
{
__be16 type;
type = skb_network_protocol(skb, NULL);
- features = net_mpls_features(skb, features, type);
+ net_mpls_features(skb, features, type);
if (skb->ip_summed != CHECKSUM_NONE &&
- !can_checksum_protocol(features, type)) {
- netdev_features_clear(features,
+ !can_checksum_protocol(*features, type)) {
+ netdev_features_clear(*features,
netdev_csum_gso_features_mask);
}
if (illegal_highdma(skb->dev, skb))
- netdev_feature_del(NETIF_F_SG_BIT, features);
-
- return features;
+ netdev_feature_del(NETIF_F_SG_BIT, *features);
}
netdev_features_t passthru_features_check(struct sk_buff *skb,
@@ -3582,7 +3574,8 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
tmp = dflt_features_check(skb, dev, features);
netdev_features_mask(features, tmp);
- return harmonize_features(skb, features);
+ harmonize_features(skb, &features);
+ return features;
}
EXPORT_SYMBOL(netif_skb_features);
@@ -3641,16 +3634,16 @@ static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
}
int skb_csum_hwoffload_help(struct sk_buff *skb,
- const netdev_features_t features)
+ const netdev_features_t *features)
{
if (unlikely(skb_csum_is_sctp(skb)))
- return netdev_feature_test(NETIF_F_SCTP_CRC_BIT, features) ? 0 :
+ return netdev_feature_test(NETIF_F_SCTP_CRC_BIT, *features) ? 0 :
skb_crc32c_csum_help(skb);
- if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features))
+ if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features))
return 0;
- if (netdev_features_intersects(features, netdev_ip_csum_features)) {
+ if (netdev_features_intersects(*features, netdev_ip_csum_features)) {
switch (skb->csum_offset) {
case offsetof(struct tcphdr, check):
case offsetof(struct udphdr, check):
@@ -3701,7 +3694,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
else
skb_set_transport_header(skb,
skb_checksum_start_offset(skb));
- if (skb_csum_hwoffload_help(skb, features))
+ if (skb_csum_hwoffload_help(skb, &features))
goto out_kfree_skb;
}
}
@@ -9567,32 +9560,31 @@ static void net_set_todo(struct net_device *dev)
atomic_inc(&dev_net(dev)->dev_unreg_count);
}
-static netdev_features_t netdev_sync_upper_features(struct net_device *lower,
- struct net_device *upper, netdev_features_t features)
+static void netdev_sync_upper_features(struct net_device *lower,
+ struct net_device *upper,
+ netdev_features_t *features)
{
netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES;
int feature_bit;
for_each_netdev_feature(upper_disables, feature_bit) {
if (!netdev_wanted_feature_test(upper, feature_bit) &&
- netdev_feature_test(feature_bit, features)) {
+ netdev_feature_test(feature_bit, *features)) {
netdev_dbg(lower, "Dropping feature bit %d, upper dev %s has it off.\n",
feature_bit, upper->name);
- netdev_feature_del(feature_bit, features);
+ netdev_feature_del(feature_bit, *features);
}
}
-
- return features;
}
static void netdev_sync_lower_features(struct net_device *upper,
- struct net_device *lower, netdev_features_t features)
+ struct net_device *lower, netdev_features_t *features)
{
netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES;
int feature_bit;
for_each_netdev_feature(upper_disables, feature_bit) {
- if (!netdev_feature_test(feature_bit, features) &&
+ if (!netdev_feature_test(feature_bit, *features) &&
netdev_active_feature_test(lower, feature_bit)) {
netdev_dbg(upper, "Disabling feature bit %d on lower dev %s.\n",
feature_bit, lower->name);
@@ -9608,116 +9600,114 @@ static void netdev_sync_lower_features(struct net_device *upper,
}
}
-static netdev_features_t netdev_fix_features(struct net_device *dev,
- netdev_features_t features)
+static void netdev_fix_features(struct net_device *dev,
+ netdev_features_t *features)
{
netdev_features_t tmp;
/* Fix illegal checksum combinations */
- if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) &&
- netdev_features_intersects(features, netdev_ip_csum_features)) {
+ if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features) &&
+ netdev_features_intersects(*features, netdev_ip_csum_features)) {
netdev_warn(dev, "mixed HW and IP checksum settings.\n");
- netdev_features_clear(features, netdev_ip_csum_features);
+ netdev_features_clear(*features, netdev_ip_csum_features);
}
/* TSO requires that SG is present as well. */
- if (netdev_features_intersects(features, NETIF_F_ALL_TSO) &&
- !netdev_feature_test(NETIF_F_SG_BIT, features)) {
+ if (netdev_features_intersects(*features, NETIF_F_ALL_TSO) &&
+ !netdev_feature_test(NETIF_F_SG_BIT, *features)) {
netdev_dbg(dev, "Dropping TSO features since no SG feature.\n");
- netdev_features_clear(features, NETIF_F_ALL_TSO);
+ netdev_features_clear(*features, NETIF_F_ALL_TSO);
}
- if (netdev_feature_test(NETIF_F_TSO_BIT, features) &&
- !netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) &&
- !netdev_feature_test(NETIF_F_IP_CSUM_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_TSO_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_IP_CSUM_BIT, *features)) {
netdev_dbg(dev, "Dropping TSO features since no CSUM feature.\n");
- netdev_feature_del(NETIF_F_TSO_BIT, features);
- netdev_feature_del(NETIF_F_TSO_ECN_BIT, features);
+ netdev_feature_del(NETIF_F_TSO_BIT, *features);
+ netdev_feature_del(NETIF_F_TSO_ECN_BIT, *features);
}
- if (netdev_feature_test(NETIF_F_TSO6_BIT, features) &&
- !netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) &&
- !netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_TSO6_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, *features)) {
netdev_dbg(dev, "Dropping TSO6 features since no CSUM feature.\n");
- netdev_feature_del(NETIF_F_TSO6_BIT, features);
+ netdev_feature_del(NETIF_F_TSO6_BIT, *features);
}
/* TSO with IPv4 ID mangling requires IPv4 TSO be enabled */
- if (netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features) &&
- !netdev_feature_test(NETIF_F_TSO_BIT, features))
- netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT, features);
+ if (netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_TSO_BIT, *features))
+ netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT, *features);
/* TSO ECN requires that TSO is present as well. */
tmp = NETIF_F_ALL_TSO;
netdev_feature_del(NETIF_F_TSO_ECN_BIT, tmp);
- if (!netdev_features_intersects(features, tmp) &&
- netdev_feature_test(NETIF_F_TSO_ECN_BIT, features))
- netdev_feature_del(NETIF_F_TSO_ECN_BIT, features);
+ if (!netdev_features_intersects(*features, tmp) &&
+ netdev_feature_test(NETIF_F_TSO_ECN_BIT, *features))
+ netdev_feature_del(NETIF_F_TSO_ECN_BIT, *features);
/* Software GSO depends on SG. */
- if (netdev_feature_test(NETIF_F_GSO_BIT, features) &&
- !netdev_feature_test(NETIF_F_SG_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_GSO_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_SG_BIT, *features)) {
netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
- netdev_feature_del(NETIF_F_GSO_BIT, features);
+ netdev_feature_del(NETIF_F_GSO_BIT, *features);
}
/* GSO partial features require GSO partial be set */
- if (netdev_gso_partial_features_intersects(dev, features) &&
- !netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) {
+ if (netdev_gso_partial_features_intersects(dev, *features) &&
+ !netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, *features)) {
netdev_dbg(dev,
"Dropping partially supported GSO features since no GSO partial.\n");
- netdev_features_clear(features, dev->gso_partial_features);
+ netdev_features_clear(*features, dev->gso_partial_features);
}
- if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+ if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features)) {
/* NETIF_F_GRO_HW implies doing RXCSUM since every packet
* successfully merged by hardware must also have the
* checksum verified by hardware. If the user does not
* want to enable RXCSUM, logically, we should disable GRO_HW.
*/
- if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_GRO_HW_BIT, *features)) {
netdev_dbg(dev, "Dropping NETIF_F_GRO_HW since no RXCSUM feature.\n");
- netdev_feature_del(NETIF_F_GRO_HW_BIT, features);
+ netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
}
}
/* LRO/HW-GRO features cannot be combined with RX-FCS */
- if (netdev_feature_test(NETIF_F_RXFCS_BIT, features)) {
- if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_RXFCS_BIT, *features)) {
+ if (netdev_feature_test(NETIF_F_LRO_BIT, *features)) {
netdev_dbg(dev, "Dropping LRO feature since RX-FCS is requested.\n");
- netdev_feature_del(NETIF_F_LRO_BIT, features);
+ netdev_feature_del(NETIF_F_LRO_BIT, *features);
}
- if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_GRO_HW_BIT, *features)) {
netdev_dbg(dev, "Dropping HW-GRO feature since RX-FCS is requested.\n");
- netdev_feature_del(NETIF_F_GRO_HW_BIT, features);
+ netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
}
}
- if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features) &&
- netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_GRO_HW_BIT, *features) &&
+ netdev_feature_test(NETIF_F_LRO_BIT, *features)) {
netdev_dbg(dev, "Dropping LRO feature since HW-GRO is requested.\n");
- netdev_feature_del(NETIF_F_LRO_BIT, features);
+ netdev_feature_del(NETIF_F_LRO_BIT, *features);
}
- if (netdev_feature_test(NETIF_F_HW_TLS_TX_BIT, features)) {
- bool ip_csum = netdev_features_subset(netdev_ip_csum_features, features);
+ if (netdev_feature_test(NETIF_F_HW_TLS_TX_BIT, *features)) {
+ bool ip_csum = netdev_features_subset(netdev_ip_csum_features, *features);
bool hw_csum = netdev_feature_test(NETIF_F_HW_CSUM_BIT,
- features);
+ *features);
if (!ip_csum && !hw_csum) {
netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n");
- netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, features);
+ netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, *features);
}
}
- if (netdev_feature_test(NETIF_F_HW_TLS_RX_BIT, features) &&
- !netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+ if (netdev_feature_test(NETIF_F_HW_TLS_RX_BIT, *features) &&
+ !netdev_feature_test(NETIF_F_RXCSUM_BIT, *features)) {
netdev_dbg(dev, "Dropping TLS RX HW offload feature since no RXCSUM feature.\n");
- netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, features);
+ netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, *features);
}
-
- return features;
}
int __netdev_update_features(struct net_device *dev)
@@ -9729,17 +9719,17 @@ int __netdev_update_features(struct net_device *dev)
ASSERT_RTNL();
- features = netdev_get_wanted_features(dev);
+ netdev_get_wanted_features(dev, &features);
if (dev->netdev_ops->ndo_fix_features)
features = dev->netdev_ops->ndo_fix_features(dev, features);
/* driver might be less strict about feature dependencies */
- features = netdev_fix_features(dev, features);
+ netdev_fix_features(dev, &features);
/* some features can't be enabled if they're off on an upper device */
netdev_for_each_upper_dev_rcu(dev, upper, iter)
- features = netdev_sync_upper_features(dev, upper, features);
+ netdev_sync_upper_features(dev, upper, &features);
if (netdev_active_features_equal(dev, features))
goto sync_lower;
@@ -9767,7 +9757,7 @@ int __netdev_update_features(struct net_device *dev)
* on an upper device (think: bonding master or bridge)
*/
netdev_for_each_lower_dev(dev, lower, iter)
- netdev_sync_lower_features(dev, lower, features);
+ netdev_sync_lower_features(dev, lower, &features);
if (!err) {
netdev_features_t diff;
@@ -448,7 +448,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
netdev_features_zero(feats);
/* Complete checksum if needed */
if (skb->ip_summed == CHECKSUM_PARTIAL &&
- (err = skb_csum_hwoffload_help(skb, feats)))
+ (err = skb_csum_hwoffload_help(skb, &feats)))
goto out;
/* Older versions of OVS user space enforce alignment of the last
There are several functions in net/core/dev.c using netdev_features_t as parameters, or returns netdev_features_t directly, or both. For the prototype of netdev_features_t will be extended to be larger than 8 bytes, so change the prototype of the function, change the prototype of input features to 'netdev_features_t *', and return the features pointer as output parameters. Signed-off-by: Jian Shen <shenjian15@huawei.com> --- include/linux/netdev_feature_helpers.h | 11 +- include/linux/netdevice.h | 2 +- net/core/dev.c | 160 ++++++++++++------------- net/openvswitch/datapath.c | 2 +- 4 files changed, 81 insertions(+), 94 deletions(-)