From 6ce1df88b1f31f0e19372afe127cf5678d63c559 Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Wed, 22 Jun 2022 15:37:03 -0700 Subject: net/funeth: Support UDP segmentation offload Handle skbs with SKB_GSO_UDP_L4, advertise the offload in features, and add an ethtool counter for it. Small change to existing TSO code due to UDP's different header length. Signed-off-by: Dimitris Michailidis Link: https://lore.kernel.org/r/20220622223703.59886-1-dmichail@fungible.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/fungible/funeth/funeth_ethtool.c | 2 ++ drivers/net/ethernet/fungible/funeth/funeth_main.c | 3 ++- drivers/net/ethernet/fungible/funeth/funeth_tx.c | 23 +++++++++++++++++++++- drivers/net/ethernet/fungible/funeth/funeth_txrx.h | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/fungible') diff --git a/drivers/net/ethernet/fungible/funeth/funeth_ethtool.c b/drivers/net/ethernet/fungible/funeth/funeth_ethtool.c index d081168c95fa..da42dd53a87c 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_ethtool.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_ethtool.c @@ -78,6 +78,7 @@ static const char * const txq_stat_names[] = { "tx_cso", "tx_tso", "tx_encapsulated_tso", + "tx_uso", "tx_more", "tx_queue_stops", "tx_queue_restarts", @@ -778,6 +779,7 @@ static void fun_get_ethtool_stats(struct net_device *netdev, ADD_STAT(txs.tx_cso); ADD_STAT(txs.tx_tso); ADD_STAT(txs.tx_encap_tso); + ADD_STAT(txs.tx_uso); ADD_STAT(txs.tx_more); ADD_STAT(txs.tx_nstops); ADD_STAT(txs.tx_nrestarts); diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c index 9485cf699c5d..f247b7ad3a88 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_main.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c @@ -1357,7 +1357,8 @@ static const struct net_device_ops fun_netdev_ops = { #define GSO_ENCAP_FLAGS (NETIF_F_GSO_GRE | NETIF_F_GSO_IPXIP4 | \ NETIF_F_GSO_IPXIP6 | NETIF_F_GSO_UDP_TUNNEL | \ NETIF_F_GSO_UDP_TUNNEL_CSUM) -#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) +#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | \ + NETIF_F_GSO_UDP_L4) #define VLAN_FEAT (NETIF_F_SG | NETIF_F_HW_CSUM | TSO_FLAGS | \ GSO_ENCAP_FLAGS | NETIF_F_HIGHDMA) diff --git a/drivers/net/ethernet/fungible/funeth/funeth_tx.c b/drivers/net/ethernet/fungible/funeth/funeth_tx.c index ff6e29237253..0a4a590218ba 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_tx.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_tx.c @@ -130,6 +130,7 @@ static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q, struct fun_dataop_gl *gle; const struct tcphdr *th; unsigned int ngle, i; + unsigned int l4_hlen; u16 flags; if (unlikely(map_skb(skb, q->dma_dev, addrs, lens))) { @@ -178,6 +179,7 @@ static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q, FUN_ETH_UPDATE_INNER_L3_LEN; } th = inner_tcp_hdr(skb); + l4_hlen = __tcp_hdrlen(th); fun_eth_offload_init(&req->offload, flags, shinfo->gso_size, tcp_hdr_doff_flags(th), 0, @@ -185,6 +187,24 @@ static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q, skb_inner_transport_offset(skb), skb_network_offset(skb), ol4_ofst); FUN_QSTAT_INC(q, tx_encap_tso); + } else if (shinfo->gso_type & SKB_GSO_UDP_L4) { + flags = FUN_ETH_INNER_LSO | FUN_ETH_INNER_UDP | + FUN_ETH_UPDATE_INNER_L4_CKSUM | + FUN_ETH_UPDATE_INNER_L4_LEN | + FUN_ETH_UPDATE_INNER_L3_LEN; + + if (ip_hdr(skb)->version == 4) + flags |= FUN_ETH_UPDATE_INNER_L3_CKSUM; + else + flags |= FUN_ETH_INNER_IPV6; + + l4_hlen = sizeof(struct udphdr); + fun_eth_offload_init(&req->offload, flags, + shinfo->gso_size, + cpu_to_be16(l4_hlen << 10), 0, + skb_network_offset(skb), + skb_transport_offset(skb), 0, 0); + FUN_QSTAT_INC(q, tx_uso); } else { /* HW considers one set of headers as inner */ flags = FUN_ETH_INNER_LSO | @@ -195,6 +215,7 @@ static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q, else flags |= FUN_ETH_UPDATE_INNER_L3_CKSUM; th = tcp_hdr(skb); + l4_hlen = __tcp_hdrlen(th); fun_eth_offload_init(&req->offload, flags, shinfo->gso_size, tcp_hdr_doff_flags(th), 0, @@ -209,7 +230,7 @@ static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q, extra_pkts = shinfo->gso_segs - 1; extra_bytes = (be16_to_cpu(req->offload.inner_l4_off) + - __tcp_hdrlen(th)) * extra_pkts; + l4_hlen) * extra_pkts; } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { flags = FUN_ETH_UPDATE_INNER_L4_CKSUM; if (skb->csum_offset == offsetof(struct udphdr, check)) diff --git a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h index 04c9f91b7489..1711f82cad71 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h +++ b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h @@ -82,6 +82,7 @@ struct funeth_txq_stats { /* per Tx queue SW counters */ u64 tx_cso; /* # of packets with checksum offload */ u64 tx_tso; /* # of non-encapsulated TSO super-packets */ u64 tx_encap_tso; /* # of encapsulated TSO super-packets */ + u64 tx_uso; /* # of non-encapsulated UDP LSO super-packets */ u64 tx_more; /* # of DBs elided due to xmit_more */ u64 tx_nstops; /* # of times the queue has stopped */ u64 tx_nrestarts; /* # of times the queue has restarted */ -- cgit v1.2.3-59-g8ed1b