@@ -7860,6 +7860,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
{
u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
struct sk_buff *segs, *seg, *next;
+ netdev_features_t features;
/* Estimate the number of fragments in the worst case */
if (unlikely(tg3_tx_avail(tnapi) <= frag_cnt_est)) {
@@ -7877,8 +7878,8 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
netif_tx_wake_queue(txq);
}
- segs = skb_gso_segment(skb, tp->dev->features &
- ~netdev_general_tso_features);
+ features = tp->dev->features & ~netdev_general_tso_features;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR(segs) || !segs)
goto tg3_tso_bug_end;
@@ -2894,10 +2894,12 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
{
struct sk_buff *segs, *curr, *next;
struct myri10ge_priv *mgp = netdev_priv(dev);
+ netdev_features_t features = dev->features;
struct myri10ge_slice_state *ss;
netdev_tx_t status;
- segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
+ features &= ~NETIF_F_TSO6;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR(segs))
goto drop;
@@ -11,6 +11,7 @@
#define EFX_NET_DRIVER_H
#include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
@@ -432,8 +432,10 @@ int efx_siena_tx_tso_fallback(struct efx_tx_queue *tx_queue,
struct sk_buff *skb)
{
struct sk_buff *segments, *next;
+ netdev_features_t feats;
- segments = skb_gso_segment(skb, 0);
+ netdev_features_zero(feats);
+ segments = skb_gso_segment(skb, feats);
if (IS_ERR(segments))
return PTR_ERR(segments);
@@ -449,8 +449,10 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
{
struct sk_buff *segments, *next;
+ netdev_features_t feats;
- segments = skb_gso_segment(skb, 0);
+ netdev_features_zero(feats);
+ segments = skb_gso_segment(skb, feats);
if (IS_ERR(segments))
return PTR_ERR(segments);
@@ -1228,6 +1228,7 @@ vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb,
int status;
int gso_size, gso_type, gso_segs;
int hlen = skb_transport_header(skb) - skb_mac_header(skb);
+ netedv_features_t features = dev->features;
int proto = IPPROTO_IP;
if (skb->protocol == htons(ETH_P_IP))
@@ -1274,7 +1275,8 @@ vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb,
skb_shinfo(skb)->gso_size = datalen;
skb_shinfo(skb)->gso_segs = gso_segs;
}
- segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO);
+ features &= ~NETIF_F_TSO;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR(segs))
goto out_dropped;
@@ -176,8 +176,11 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
if (!skb_is_gso(skb)) {
skb_mark_not_on_list(skb);
} else {
- struct sk_buff *segs = skb_gso_segment(skb, 0);
+ netdev_features_t feats;
+ struct sk_buff *segs;
+ netdev_features_zero(feats);
+ segs = skb_gso_segment(skb, feats);
if (IS_ERR(segs)) {
ret = PTR_ERR(segs);
goto err_peer;
@@ -3394,11 +3394,13 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
* work.
*/
if (features & NETIF_F_GSO_PARTIAL) {
- netdev_features_t partial_features = NETIF_F_GSO_ROBUST;
+ netdev_features_t partial_features;
struct net_device *dev = skb->dev;
- partial_features |= dev->features & dev->gso_partial_features;
- if (!skb_gso_ok(skb, features | partial_features))
+ partial_features = dev->features & dev->gso_partial_features;
+ partial_features |= NETIF_F_GSO_ROBUST;
+ partial_features |= features;
+ if (!skb_gso_ok(skb, partial_features))
features &= ~NETIF_F_GSO_PARTIAL;
}
@@ -264,7 +264,8 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,
*/
features = netif_skb_features(skb);
BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);
- segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ features &= ~NETIF_F_GSO_MASK;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR_OR_NULL(segs)) {
kfree_skb(skb);
return -ENOMEM;
@@ -82,7 +82,8 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
if (unlikely(skb->len <= mss))
goto out;
- if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+ features |= NETIF_F_GSO_ROBUST;
+ if (skb_gso_ok(skb, features)) {
/* Packet is from an untrusted source, reset gso_segs. */
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
@@ -149,7 +149,8 @@ ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
* egress MTU.
*/
features = netif_skb_features(skb);
- segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ features &= ~NETIF_F_GSO_MASK;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR_OR_NULL(segs)) {
kfree_skb(skb);
return -ENOMEM;
@@ -4203,9 +4203,11 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
}
if (skb_is_gso(skb)) {
+ netdev_features_t feats;
struct sk_buff *segs;
- segs = skb_gso_segment(skb, 0);
+ netdev_features_zero(feats);
+ segs = skb_gso_segment(skb, feats);
if (IS_ERR(segs)) {
goto out_free;
} else if (segs) {
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
#include <linux/netfilter.h>
#include <linux/proc_fs.h>
#include <linux/netfilter_ipv4.h>
@@ -788,6 +789,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
int err = -ENOBUFS;
struct net *net = entry->state.net;
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+ netdev_features_t feats;
/* rcu_read_lock()ed by nf_hook_thresh */
queue = instance_lookup(q, queuenum);
@@ -812,7 +814,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
return __nfqnl_enqueue_packet(net, queue, entry);
nf_bridge_adjust_skb_data(skb);
- segs = skb_gso_segment(skb, 0);
+ netdev_features_zero(feats);
+ segs = skb_gso_segment(skb, feats);
/* Does not use PTR_ERR to limit the number of error codes that can be
* returned by nf_queue. For instance, callers rely on -ESRCH to
* mean 'ignore this hook'.
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
#include <linux/skbuff.h>
#include <net/nsh.h>
#include <net/tun_proto.h>
@@ -78,6 +79,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
unsigned int nsh_len, mac_len;
+ netdev_features_t feats;
__be16 proto;
int nhoff;
@@ -104,8 +106,10 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0;
skb->protocol = proto;
- features &= NETIF_F_SG;
- segs = skb_mac_gso_segment(skb, features);
+ netdev_features_zero(feats);
+ if (features & NETIF_F_SG)
+ feats |= NETIF_F_SG;
+ segs = skb_mac_gso_segment(skb, feats);
if (IS_ERR_OR_NULL(segs)) {
skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
skb->network_header - nhoff,
@@ -27,6 +27,7 @@
#include <linux/wait.h>
#include <asm/div64.h>
#include <linux/highmem.h>
+#include <linux/netdev_feature_helpers.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
#include <linux/inetdevice.h>
@@ -328,10 +329,13 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
unsigned int gso_type = skb_shinfo(skb)->gso_type;
struct sw_flow_key later_key;
struct sk_buff *segs, *nskb;
+ netdev_features_t features;
int err;
BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
- segs = __skb_gso_segment(skb, NETIF_F_SG, false);
+ netdev_features_zero(features);
+ features |= NETIF_F_SG;
+ segs = __skb_gso_segment(skb, features, false);
if (IS_ERR(segs))
return PTR_ERR(segs);
if (segs == NULL)
@@ -1743,7 +1743,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
netdev_features_t features = netif_skb_features(skb);
unsigned int slen = 0, numsegs = 0;
- segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ features &= ~NETIF_F_GSO_MASK;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR_OR_NULL(segs))
return qdisc_drop(skb, sch, to_free);
@@ -415,7 +415,8 @@ static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff *segs;
netdev_features_t features = netif_skb_features(skb);
- segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ features &= ~NETIF_F_GSO_MASK;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR_OR_NULL(segs)) {
qdisc_drop(skb, sch, to_free);
@@ -463,7 +463,8 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff *segs, *nskb;
int ret;
- segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ features &= ~NETIF_F_GSO_MASK;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR_OR_NULL(segs))
return qdisc_drop(skb, sch, to_free);
@@ -210,7 +210,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
int ret, nb;
- segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ features &= ~NETIF_F_GSO_MASK;
+ segs = skb_gso_segment(skb, features);
if (IS_ERR_OR_NULL(segs))
return qdisc_drop(skb, sch, to_free);
@@ -39,6 +39,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
+ netdev_features_t tmp = features;
struct sctphdr *sh;
if (!skb_is_gso_sctp(skb))
@@ -50,7 +51,8 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
__skb_pull(skb, sizeof(*sh));
- if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+ tmp |= NETIF_F_GSO_ROBUST;
+ if (skb_gso_ok(skb, tmp)) {
/* Packet is from an untrusted source, reset gso_segs. */
struct skb_shared_info *pinfo = skb_shinfo(skb);
struct sk_buff *frag_iter;
@@ -68,7 +70,10 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
goto out;
}
- segs = skb_segment(skb, (features | NETIF_F_HW_CSUM) & ~NETIF_F_SG);
+ tmp = features;
+ tmp |= NETIF_F_HW_CSUM;
+ tmp &= ~NETIF_F_SG;
+ segs = skb_segment(skb, tmp);
if (IS_ERR(segs))
goto out;
@@ -138,7 +138,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
struct sk_buff *segs;
/* Packet got rerouted, fixup features and segment it. */
- esp_features = esp_features & ~(NETIF_F_HW_ESP | NETIF_F_GSO_ESP);
+ esp_features &= ~NETIF_F_HW_ESP;
+ esp_features &= ~NETIF_F_GSO_ESP;
segs = skb_gso_segment(skb, esp_features);
if (IS_ERR(segs)) {
@@ -8,6 +8,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
@@ -618,10 +619,12 @@ static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct sk_buff *segs, *nskb;
+ netdev_features_t feats;
BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);
BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_GSO_CB_OFFSET);
- segs = skb_gso_segment(skb, 0);
+ netdev_features_zero(feats);
+ segs = skb_gso_segment(skb, feats);
kfree_skb(skb);
if (IS_ERR(segs))
return PTR_ERR(segs);
The xxx_gso_segment functions use netdev features as input parameter. Some of them using features handling expression directly. Simplify these expreesions, so it can be replaced by netdev features helpers later. Signed-off-by: Jian Shen <shenjian15@huawei.com> --- drivers/net/ethernet/broadcom/tg3.c | 5 +++-- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 4 +++- drivers/net/ethernet/sfc/siena/net_driver.h | 1 + drivers/net/ethernet/sfc/siena/tx_common.c | 4 +++- drivers/net/ethernet/sfc/tx_common.c | 4 +++- drivers/net/ethernet/sun/sunvnet_common.c | 4 +++- drivers/net/wireguard/device.c | 5 ++++- net/core/dev.c | 8 +++++--- net/ipv4/ip_output.c | 3 ++- net/ipv4/tcp_offload.c | 3 ++- net/ipv6/ip6_output.c | 3 ++- net/mac80211/tx.c | 4 +++- net/netfilter/nfnetlink_queue.c | 5 ++++- net/nsh/nsh.c | 8 ++++++-- net/openvswitch/datapath.c | 6 +++++- net/sched/sch_cake.c | 3 ++- net/sched/sch_netem.c | 3 ++- net/sched/sch_taprio.c | 3 ++- net/sched/sch_tbf.c | 3 ++- net/sctp/offload.c | 9 +++++++-- net/xfrm/xfrm_device.c | 3 ++- net/xfrm/xfrm_output.c | 5 ++++- 22 files changed, 70 insertions(+), 26 deletions(-)