Skip to content

Commit 18de1e5

Browse files
Eric Dumazetdavem330
Eric Dumazet
authored andcommitted
gve: add gve_features_check()
It is suboptimal to attempt skb linearization from ndo_start_xmit() if a gso skb has pathological layout, or if host stack does not have access to the payload (TCP direct). Linearization of large skbs can also fail under memory pressure. We should instead have an ndo_features_check() so that we can fallback to GSO, which is supported even for TCP direct, and generally much more efficient (no payload copy). Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Bailey Forrest <bcf@google.com> Cc: Willem de Bruijn <willemb@google.com> Cc: Jeroen de Borst <jeroendb@google.com> Cc: Praveen Kaligineedi <pkaligineedi@google.com> Cc: Shailend Chand <shailend@google.com> Cc: Ziwei Xiao <ziweixiao@google.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 380b50a commit 18de1e5

File tree

3 files changed

+31
-22
lines changed

3 files changed

+31
-22
lines changed

drivers/net/ethernet/google/gve/gve_dqo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#define GVE_DEALLOCATE_COMPL_TIMEOUT 60
3434

3535
netdev_tx_t gve_tx_dqo(struct sk_buff *skb, struct net_device *dev);
36+
netdev_features_t gve_features_check_dqo(struct sk_buff *skb,
37+
struct net_device *dev,
38+
netdev_features_t features);
3639
bool gve_tx_poll_dqo(struct gve_notify_block *block, bool do_clean);
3740
int gve_rx_poll_dqo(struct gve_notify_block *block, int budget);
3841
int gve_tx_alloc_rings_dqo(struct gve_priv *priv);

drivers/net/ethernet/google/gve/gve_main.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ static int gve_verify_driver_compatibility(struct gve_priv *priv)
7979
return err;
8080
}
8181

82+
static netdev_features_t gve_features_check(struct sk_buff *skb,
83+
struct net_device *dev,
84+
netdev_features_t features)
85+
{
86+
struct gve_priv *priv = netdev_priv(dev);
87+
88+
if (!gve_is_gqi(priv))
89+
return gve_features_check_dqo(skb, dev, features);
90+
91+
return features;
92+
}
93+
8294
static netdev_tx_t gve_start_xmit(struct sk_buff *skb, struct net_device *dev)
8395
{
8496
struct gve_priv *priv = netdev_priv(dev);
@@ -1879,6 +1891,7 @@ static int gve_set_features(struct net_device *netdev,
18791891

18801892
static const struct net_device_ops gve_netdev_ops = {
18811893
.ndo_start_xmit = gve_start_xmit,
1894+
.ndo_features_check = gve_features_check,
18821895
.ndo_open = gve_open,
18831896
.ndo_stop = gve_close,
18841897
.ndo_get_stats64 = gve_get_stats,

drivers/net/ethernet/google/gve/gve_tx_dqo.c

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,16 @@ static bool gve_can_send_tso(const struct sk_buff *skb)
843843
return true;
844844
}
845845

846+
netdev_features_t gve_features_check_dqo(struct sk_buff *skb,
847+
struct net_device *dev,
848+
netdev_features_t features)
849+
{
850+
if (skb_is_gso(skb) && !gve_can_send_tso(skb))
851+
return features & ~NETIF_F_GSO_MASK;
852+
853+
return features;
854+
}
855+
846856
/* Attempt to transmit specified SKB.
847857
*
848858
* Returns 0 if the SKB was transmitted or dropped.
@@ -854,11 +864,10 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx,
854864
int num_buffer_descs;
855865
int total_num_descs;
856866

857-
if (tx->dqo.qpl) {
858-
if (skb_is_gso(skb))
859-
if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
860-
goto drop;
867+
if (skb_is_gso(skb) && unlikely(ipv6_hopopt_jumbo_remove(skb)))
868+
goto drop;
861869

870+
if (tx->dqo.qpl) {
862871
/* We do not need to verify the number of buffers used per
863872
* packet or per segment in case of TSO as with 2K size buffers
864873
* none of the TX packet rules would be violated.
@@ -868,24 +877,8 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx,
868877
*/
869878
num_buffer_descs = DIV_ROUND_UP(skb->len, GVE_TX_BUF_SIZE_DQO);
870879
} else {
871-
if (skb_is_gso(skb)) {
872-
/* If TSO doesn't meet HW requirements, attempt to linearize the
873-
* packet.
874-
*/
875-
if (unlikely(!gve_can_send_tso(skb) &&
876-
skb_linearize(skb) < 0)) {
877-
net_err_ratelimited("%s: Failed to transmit TSO packet\n",
878-
priv->dev->name);
879-
goto drop;
880-
}
881-
882-
if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
883-
goto drop;
884-
885-
num_buffer_descs = gve_num_buffer_descs_needed(skb);
886-
} else {
887-
num_buffer_descs = gve_num_buffer_descs_needed(skb);
888-
880+
num_buffer_descs = gve_num_buffer_descs_needed(skb);
881+
if (!skb_is_gso(skb)) {
889882
if (unlikely(num_buffer_descs > GVE_TX_MAX_DATA_DESCS)) {
890883
if (unlikely(skb_linearize(skb) < 0))
891884
goto drop;

0 commit comments

Comments
 (0)