nfp: support UDP segmentation offload
authorFei Qin <fei.qin@corigine.com>
Fri, 8 Dec 2023 06:03:01 +0000 (08:03 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 11 Dec 2023 10:01:56 +0000 (10:01 +0000)
The device supports UDP hardware segmentation offload, which helps
improving the performance. Thus, this patch adds support for UDP
segmentation offload from the driver side.

Signed-off-by: Fei Qin <fei.qin@corigine.com>
Signed-off-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/nfd3/dp.c
drivers/net/ethernet/netronome/nfp/nfdk/dp.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h

index 17381bf..d215efc 100644 (file)
@@ -74,7 +74,7 @@ static void
 nfp_nfd3_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfd3_tx_buf *txbuf,
                struct nfp_nfd3_tx_desc *txd, struct sk_buff *skb, u32 md_bytes)
 {
-       u32 l3_offset, l4_offset, hdrlen;
+       u32 l3_offset, l4_offset, hdrlen, l4_hdrlen;
        u16 mss;
 
        if (!skb_is_gso(skb))
@@ -83,13 +83,16 @@ nfp_nfd3_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfd3_tx_buf *txbuf,
        if (!skb->encapsulation) {
                l3_offset = skb_network_offset(skb);
                l4_offset = skb_transport_offset(skb);
-               hdrlen = skb_tcp_all_headers(skb);
+               l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
+                           sizeof(struct udphdr) : tcp_hdrlen(skb);
        } else {
                l3_offset = skb_inner_network_offset(skb);
                l4_offset = skb_inner_transport_offset(skb);
-               hdrlen = skb_inner_tcp_all_headers(skb);
+               l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
+                           sizeof(struct udphdr) : inner_tcp_hdrlen(skb);
        }
 
+       hdrlen = l4_offset + l4_hdrlen;
        txbuf->pkt_cnt = skb_shinfo(skb)->gso_segs;
        txbuf->real_len += hdrlen * (txbuf->pkt_cnt - 1);
 
index 8d78c6f..dae5af7 100644 (file)
@@ -40,20 +40,23 @@ static __le64
 nfp_nfdk_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfdk_tx_buf *txbuf,
                struct sk_buff *skb)
 {
-       u32 segs, hdrlen, l3_offset, l4_offset;
+       u32 segs, hdrlen, l3_offset, l4_offset, l4_hdrlen;
        struct nfp_nfdk_tx_desc txd;
        u16 mss;
 
        if (!skb->encapsulation) {
                l3_offset = skb_network_offset(skb);
                l4_offset = skb_transport_offset(skb);
-               hdrlen = skb_tcp_all_headers(skb);
+               l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
+                           sizeof(struct udphdr) : tcp_hdrlen(skb);
        } else {
                l3_offset = skb_inner_network_offset(skb);
                l4_offset = skb_inner_transport_offset(skb);
-               hdrlen = skb_inner_tcp_all_headers(skb);
+               l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
+                           sizeof(struct udphdr) : inner_tcp_hdrlen(skb);
        }
 
+       hdrlen = l4_offset + l4_hdrlen;
        segs = skb_shinfo(skb)->gso_segs;
        mss = skb_shinfo(skb)->gso_size & NFDK_DESC_TX_MSS_MASK;
 
index dcd27ba..3b3210d 100644 (file)
@@ -2116,7 +2116,10 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
        if (skb_is_gso(skb)) {
                u32 hdrlen;
 
-               hdrlen = skb_inner_tcp_all_headers(skb);
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
+                       hdrlen = skb_inner_transport_offset(skb) + sizeof(struct udphdr);
+               else
+                       hdrlen = skb_inner_tcp_all_headers(skb);
 
                /* Assume worst case scenario of having longest possible
                 * metadata prepend - 8B
@@ -2419,7 +2422,7 @@ void nfp_net_info(struct nfp_net *nn)
                nn->fw_ver.extend, nn->fw_ver.class,
                nn->fw_ver.major, nn->fw_ver.minor,
                nn->max_mtu);
-       nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+       nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
                nn->cap,
                nn->cap & NFP_NET_CFG_CTRL_PROMISC  ? "PROMISC "  : "",
                nn->cap & NFP_NET_CFG_CTRL_L2BC     ? "L2BCFILT " : "",
@@ -2448,6 +2451,7 @@ void nfp_net_info(struct nfp_net *nn)
                                                      "RXCSUM_COMPLETE " : "",
                nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "",
                nn->cap_w1 & NFP_NET_CFG_CTRL_MCAST_FILTER ? "MULTICAST_FILTER " : "",
+               nn->cap_w1 & NFP_NET_CFG_CTRL_USO ? "USO " : "",
                nfp_app_extra_cap(nn->app, nn));
 }
 
@@ -2696,6 +2700,8 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
        if ((nn->cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
            nn->cap & NFP_NET_CFG_CTRL_LSO2) {
                netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+               if (nn->cap_w1 & NFP_NET_CFG_CTRL_USO)
+                       netdev->hw_features |= NETIF_F_GSO_UDP_L4;
                nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
                                         NFP_NET_CFG_CTRL_LSO;
        }
index eaf4d3c..634c63c 100644 (file)
 #define   NFP_NET_CFG_CTRL_MCAST_FILTER          (0x1 << 2) /* Multicast Filter */
 #define   NFP_NET_CFG_CTRL_FREELIST_EN   (0x1 << 6) /* Freelist enable flag bit */
 #define   NFP_NET_CFG_CTRL_FLOW_STEER    (0x1 << 8) /* Flow steering */
+#define   NFP_NET_CFG_CTRL_USO           (0x1 << 16) /* UDP segmentation offload */
 
 #define NFP_NET_CFG_CAP_WORD1          0x00a4