diff mbox series

[ovs-dev,[PATCH,RFC] 12/17] Show netdev offloading flags.

Message ID 20211207165156.705727-13-fbl@sysclose.org
State RFC
Headers show
Series [ovs-dev,[PATCH,RFC] 12/17] Show netdev offloading flags. | expand

Commit Message

Flavio Leitner Dec. 7, 2021, 4:51 p.m. UTC
Add a new command to show the offloading features of
each data path port.

Signed-off-by: Flavio Leitner <fbl@sysclose.org>
---
 lib/dpif-netdev-unixctl.man |  5 ++++
 lib/dpif-netdev.c           | 58 +++++++++++++++++++++++++++++++++++++
 lib/netdev-provider.h       |  3 ++
 lib/netdev.c                | 35 ++++++++++++++++++++++
 tests/dpif-netdev.at        | 21 ++++++++++++++
 5 files changed, 122 insertions(+)
diff mbox series

Patch

diff --git a/lib/dpif-netdev-unixctl.man b/lib/dpif-netdev-unixctl.man
index 607750bad..da64f89d6 100644
--- a/lib/dpif-netdev-unixctl.man
+++ b/lib/dpif-netdev-unixctl.man
@@ -260,3 +260,8 @@  PMDs in the case where no value is specified.  By default "scalar" is used.
 \fIstudy_cnt\fR defaults to 128 and indicates the number of packets that the
 "study" miniflow implementation must parse before choosing an optimal
 implementation.
+.IP "\fBdpif-netdev/offload-show\fR [\fIdp\fR] [\fInetdev\fR]"
+Prints the hardware offloading features enabled in netdev \fInetdev\fR
+attached to datapath \fIdp\fR. The datapath \fIdp\fR parameter can be
+omitted if there is only one. All netdev ports are printed if the
+parameter \fInetdev\fR is omitted.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 69d7ec26e..a525ab1e9 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1491,6 +1491,61 @@  dpif_netdev_bond_show(struct unixctl_conn *conn, int argc,
     ds_destroy(&reply);
 }
 
+static void
+dpif_netdev_offload_show(struct unixctl_conn *conn, int argc,
+                         const char *argv[], void *aux OVS_UNUSED)
+{
+    struct ds reply = DS_EMPTY_INITIALIZER;
+    const char *netdev_name = NULL;
+    struct dp_netdev *dp = NULL;
+    struct dp_netdev_port *port;
+
+    ovs_mutex_lock(&dp_netdev_mutex);
+    if (argc == 3) {
+        dp = shash_find_data(&dp_netdevs, argv[1]);
+        netdev_name = argv[2];
+    } else if (argc == 2) {
+        dp = shash_find_data(&dp_netdevs, argv[1]);
+        if (!dp && shash_count(&dp_netdevs) == 1) {
+            /* There's only one datapath. */
+            dp = shash_first(&dp_netdevs)->data;
+            netdev_name = argv[1];
+        }
+    } else if (shash_count(&dp_netdevs) == 1) {
+        /* There's only one datapath. */
+        dp = shash_first(&dp_netdevs)->data;
+    }
+
+    if (!dp) {
+        ovs_mutex_unlock(&dp_netdev_mutex);
+        unixctl_command_reply_error(conn,
+                                    "please specify an existing datapath");
+        return;
+    }
+
+    ovs_mutex_lock(&dp->port_mutex);
+    HMAP_FOR_EACH (port, node, &dp->ports) {
+        if (netdev_name) {
+            /* find the port and dump the info */
+            if (!strcmp(netdev_get_name(port->netdev), netdev_name)) {
+                ds_put_format(&reply, "%s: ", netdev_get_name(port->netdev));
+                netdev_ol_flags_to_string(&reply, port->netdev);
+                ds_put_format(&reply, "\n");
+                break;
+            }
+        } else {
+            ds_put_format(&reply, "%s: ", netdev_get_name(port->netdev));
+            netdev_ol_flags_to_string(&reply, port->netdev);
+            ds_put_format(&reply, "\n");
+        }
+    }
+
+    ovs_mutex_unlock(&dp->port_mutex);
+    ovs_mutex_unlock(&dp_netdev_mutex);
+    unixctl_command_reply(conn, ds_cstr(&reply));
+    ds_destroy(&reply);
+}
+
 
 static int
 dpif_netdev_init(void)
@@ -1547,6 +1602,9 @@  dpif_netdev_init(void)
     unixctl_command_register("dpif-netdev/miniflow-parser-get", "",
                              0, 0, dpif_miniflow_extract_impl_get,
                              NULL);
+    unixctl_command_register("dpif-netdev/offload-show", "[dp] [netdev]",
+                             0, 2, dpif_netdev_offload_show,
+                             NULL);
     return 0;
 }
 
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 0a8538615..5489ebbb8 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -37,6 +37,7 @@  extern "C" {
 struct netdev_tnl_build_header_params;
 #define NETDEV_NUMA_UNSPEC OVS_NUMA_UNSPEC
 
+/* Keep this enum updated with translation to string below. */
 enum netdev_ol_flags {
     NETDEV_OFFLOAD_TX_IPV4_CSUM = 1 << 0,
     NETDEV_OFFLOAD_TX_TCP_CSUM = 1 << 1,
@@ -45,6 +46,8 @@  enum netdev_ol_flags {
     NETDEV_OFFLOAD_TX_TCP_TSO = 1 << 4,
 };
 
+void netdev_ol_flags_to_string(struct ds *, const struct netdev *);
+
 /* A network device (e.g. an Ethernet device).
  *
  * Network device implementations may read these members but should not modify
diff --git a/lib/netdev.c b/lib/netdev.c
index 9043d5aaf..5bde9c1c9 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -2298,3 +2298,38 @@  netdev_free_custom_stats_counters(struct netdev_custom_stats *custom_stats)
         }
     }
 }
+
+void
+netdev_ol_flags_to_string(struct ds *string, const struct netdev *netdev)
+{
+    /* Sort by dependency, if any. */
+    if (netdev->ol_flags & NETDEV_OFFLOAD_TX_IPV4_CSUM) {
+        ds_put_format(string, "ip_csum: on, ");
+    } else {
+        ds_put_format(string, "ip_csum: off, ");
+    }
+
+    if (netdev->ol_flags & NETDEV_OFFLOAD_TX_TCP_CSUM) {
+        ds_put_format(string, "tcp_csum: on, ");
+    } else {
+        ds_put_format(string, "tcp_csum: off, ");
+    }
+
+    if (netdev->ol_flags & NETDEV_OFFLOAD_TX_UDP_CSUM) {
+        ds_put_format(string, "udp_csum: on, ");
+    } else {
+        ds_put_format(string, "udp_csum: off, ");
+    }
+
+    if (netdev->ol_flags & NETDEV_OFFLOAD_TX_SCTP_CSUM) {
+        ds_put_format(string, "sctp_csum: on, ");
+    } else {
+        ds_put_format(string, "sctp_csum: off, ");
+    }
+
+    if (netdev->ol_flags & NETDEV_OFFLOAD_TX_TCP_TSO) {
+        ds_put_format(string, "tso: on");
+    } else {
+        ds_put_format(string, "tso: off");
+    }
+}
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 53eee185a..13cf7ea66 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -635,3 +635,24 @@  OVS_WAIT_UNTIL([grep "flow: in_port is not an exact match" ovs-vswitchd.log])
 OVS_VSWITCHD_STOP(["/flow: in_port is not an exact match/d
 /failed to put/d"])
 AT_CLEANUP
+
+AT_SETUP([dpif-netdev - check dpif-netdev/offload-show])
+OVS_VSWITCHD_START(
+  [add-port br0 p1 \
+   -- set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p0.sock \
+   -- set bridge br0 datapath-type=dummy \
+                     other-config:datapath-id=1234 fail-mode=secure])
+
+AT_CHECK([ovs-appctl dpif-netdev/offload-show | sort], [0], [dnl
+ovs-dummy: ip_csum: off, tcp_csum: off, udp_csum: off, sctp_csum: off, tso: off
+br0: ip_csum: off, tcp_csum: off, udp_csum: off, sctp_csum: off, tso: off
+p1: ip_csum: off, tcp_csum: off, udp_csum: off, sctp_csum: off, tso: off
+], [])
+AT_CHECK([ovs-appctl dpif-netdev/offload-show p1], [0], [dnl
+p1: ip_csum: off, tcp_csum: off, udp_csum: off, sctp_csum: off, tso: off
+], [])
+AT_CHECK([ovs-appctl dpif-netdev/offload-show ovs-dummy p1], [0], [dnl
+p1: ip_csum: off, tcp_csum: off, udp_csum: off, sctp_csum: off, tso: off
+], [])
+OVS_VSWITCHD_STOP
+AT_CLEANUP