Following support of L3 and L4 checksum offloading, some bugs have been raised in different DPDK drivers. When faced with such bugs, a OVS user can't do anything but wait for a DPDK fix (which can take some time to make it to the LTS releases).
Make it possible for the user to disable some Tx offloads. Link: https://patchwork.dpdk.org/project/dpdk/patch/20230818090351.2402519-1-david.march...@redhat.com/ Link: https://patchwork.dpdk.org/project/dpdk/patch/20230822073244.3751885-1-david.march...@redhat.com/ Signed-off-by: David Marchand <david.march...@redhat.com> --- lib/netdev-provider.h | 5 ++- lib/netdev.c | 72 +++++++++++++++++++++++++++++++++++++------ tests/dpif-netdev.at | 10 ++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index a7393c7cec..32a760d826 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -59,9 +59,12 @@ struct netdev { * opening this device, and therefore got assigned to the "system" class */ bool auto_classified; - /* This bitmask of the offloading features enabled by the netdev. */ + /* Bitmask of the offloading features supported by the netdev. */ uint64_t ol_flags; + /* Bitmask of the offloading features disabled by the user. */ + uint64_t disabled_ol_flags; + /* If this is 'true', the user explicitly specified an MTU for this * netdev. Otherwise, Open vSwitch is allowed to override it. */ bool mtu_user_config; diff --git a/lib/netdev.c b/lib/netdev.c index e5ac7713d2..e86dc82301 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -490,6 +490,59 @@ netdev_ref(const struct netdev *netdev_) return netdev; } +#define NETDEV_OL_FLAGS \ + NETDEV_OL_FLAG("ip_csum", NETDEV_TX_OFFLOAD_IPV4_CKSUM); \ + NETDEV_OL_FLAG("tcp_csum", NETDEV_TX_OFFLOAD_TCP_CKSUM); \ + NETDEV_OL_FLAG("udp_csum", NETDEV_TX_OFFLOAD_UDP_CKSUM); \ + NETDEV_OL_FLAG("sctp_csum", NETDEV_TX_OFFLOAD_SCTP_CKSUM); \ + NETDEV_OL_FLAG("tcp_seg", NETDEV_TX_OFFLOAD_TCP_TSO); + +static int +netdev_parse_disabled_ol_flags(struct netdev *netdev, const struct smap *args) +{ + const char *ol_flags = NULL; + int err = 0; + + netdev->disabled_ol_flags = 0; + + if (args) { + ol_flags = smap_get(args, "disabled_ol_flags"); + } + if (ol_flags && ol_flags[0] != '\0') { + char *list = xstrdup(ol_flags); + char *ptr = list; + + while (ptr) { + char *end = strchr(ptr, ','); + bool known_ol_flag = false; + + if (end) { + end[0] = '\0'; + } +#define NETDEV_OL_FLAG(name, bit) \ + if (!strcmp(ptr, name)) { \ + netdev->disabled_ol_flags |= bit; \ + VLOG_DBG("Disabling %s on %s", name, \ + netdev_get_name(netdev)); \ + known_ol_flag = true; \ + } + NETDEV_OL_FLAGS +#undef NETDEV_OL_FLAG + if (!known_ol_flag) { + VLOG_WARN("unknown offload type '%s'", ptr); + } + if (end) { + ptr = end + 1; + } else { + ptr = NULL; + } + } + free(list); + } + + return err; +} + /* Reconfigures the device 'netdev' with 'args'. 'args' may be empty * or NULL if none are needed. */ int @@ -501,6 +554,7 @@ netdev_set_config(struct netdev *netdev, const struct smap *args, char **errp) char *verbose_error = NULL; int error; + netdev_parse_disabled_ol_flags(netdev, args); error = netdev->netdev_class->set_config(netdev, args ? args : &no_args, &verbose_error); @@ -834,9 +888,10 @@ netdev_send_prepare_batch(const struct netdev *netdev, size_t i, size = dp_packet_batch_size(batch); DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) { + uint64_t ol_flags = netdev->ol_flags & ~netdev->disabled_ol_flags; char *errormsg = NULL; - if (netdev_send_prepare_packet(netdev->ol_flags, packet, &errormsg)) { + if (netdev_send_prepare_packet(ol_flags, packet, &errormsg)) { dp_packet_batch_refill(batch, packet, i); } else { dp_packet_delete(packet); @@ -1400,16 +1455,13 @@ netdev_get_status(const struct netdev *netdev, struct smap *smap) if (netdev_get_dpif_type(netdev) && strcmp(netdev_get_dpif_type(netdev), "system")) { -#define OL_ADD_STAT(name, bit) \ +#define NETDEV_OL_FLAG(name, bit) \ smap_add(smap, "tx_" name "_offload", \ - netdev->ol_flags & bit ? "true" : "false"); - - OL_ADD_STAT("ip_csum", NETDEV_TX_OFFLOAD_IPV4_CKSUM); - OL_ADD_STAT("tcp_csum", NETDEV_TX_OFFLOAD_TCP_CKSUM); - OL_ADD_STAT("udp_csum", NETDEV_TX_OFFLOAD_UDP_CKSUM); - OL_ADD_STAT("sctp_csum", NETDEV_TX_OFFLOAD_SCTP_CKSUM); - OL_ADD_STAT("tcp_seg", NETDEV_TX_OFFLOAD_TCP_TSO); -#undef OL_ADD_STAT + netdev->ol_flags & bit \ + ? (netdev->disabled_ol_flags & bit ? "disabled" : "true") \ + : "false"); + NETDEV_OL_FLAGS +#undef NETDEV_OL_FLAG err = 0; } diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at index 85119fb819..922badd90c 100644 --- a/tests/dpif-netdev.at +++ b/tests/dpif-netdev.at @@ -665,6 +665,16 @@ AT_CHECK([ovs-vsctl get interface br0 status | sed -n 's/^{\(.*\).*}$/\1/p'], [0 tx_ip_csum_offload="false", tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false" ], []) +AT_CHECK([ovs-vsctl set Interface p1 options:ol_ip_csum=true]) +AT_CHECK([ovs-vsctl get interface p1 status | sed -n 's/^{\(.*\).*}$/\1/p'], [0], [dnl +tx_ip_csum_offload="true", tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false" +], []) + +AT_CHECK([ovs-vsctl set Interface p1 options:disabled_ol_flags="ip_csum"]) +AT_CHECK([ovs-vsctl get interface p1 status | sed -n 's/^{\(.*\).*}$/\1/p'], [0], [dnl +tx_ip_csum_offload=disabled, tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false" +], []) + OVS_VSWITCHD_STOP AT_CLEANUP -- 2.41.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev