From 64dd1720e5fd6f0cd9b029a5bc312e7264ac7d24 Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Thu, 17 Jun 2021 17:20:02 +0000 Subject: dpdk: add support for outer udp and ipv4 checksums Type: improvement Signed-off-by: Mohsin Kazmi Change-Id: I10141033030342881298d70742fa5bdea402b4c9 --- extras/vpp_config/data/startup.conf.template | 4 +++ src/plugins/dpdk/device/device.c | 38 +++++++++++++++++++----- src/plugins/dpdk/device/dpdk.h | 1 + src/plugins/dpdk/device/init.c | 43 ++++++++++++++++++++++------ 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/extras/vpp_config/data/startup.conf.template b/extras/vpp_config/data/startup.conf.template index 13d86b6c384..ccd2cf34a4e 100644 --- a/extras/vpp_config/data/startup.conf.template +++ b/extras/vpp_config/data/startup.conf.template @@ -150,6 +150,10 @@ dpdk {{ ## Enable UDP / TCP TX checksum offload ## This is the reversed option of 'no-tx-checksum-offload' # enable-tcp-udp-checksum + + ## Enable outer UDP / IPv4 checksum offload + ## This is only enabled when tunnels offload are available + # enable-outer-checksum-offload }} ## node variant defaults diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c index 7c083e1dcf4..095036fcb5c 100644 --- a/src/plugins/dpdk/device/device.c +++ b/src/plugins/dpdk/device/device.c @@ -221,7 +221,8 @@ dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b, { int is_ip4 = b->flags & VNET_BUFFER_F_IS_IP4; u32 tso = b->flags & VNET_BUFFER_F_GSO, max_pkt_len; - u32 ip_cksum, tcp_cksum, udp_cksum; + u32 ip_cksum, tcp_cksum, udp_cksum, outer_hdr_len = 0; + u32 outer_ip_cksum, vxlan_tunnel; u64 ol_flags; vnet_buffer_oflags_t oflags = 0; @@ -233,23 +234,46 @@ dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b, ip_cksum = oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM; tcp_cksum = oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM; udp_cksum = oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM; + outer_ip_cksum = oflags & VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM; + vxlan_tunnel = oflags & VNET_BUFFER_OFFLOAD_F_TNL_VXLAN; - mb->l2_len = vnet_buffer (b)->l3_hdr_offset - b->current_data; - mb->l3_len = vnet_buffer (b)->l4_hdr_offset - - vnet_buffer (b)->l3_hdr_offset; - mb->outer_l3_len = 0; - mb->outer_l2_len = 0; ol_flags = is_ip4 ? PKT_TX_IPV4 : PKT_TX_IPV6; ol_flags |= ip_cksum ? PKT_TX_IP_CKSUM : 0; ol_flags |= tcp_cksum ? PKT_TX_TCP_CKSUM : 0; ol_flags |= udp_cksum ? PKT_TX_UDP_CKSUM : 0; + if (vxlan_tunnel) + { + ol_flags |= outer_ip_cksum ? PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IP_CKSUM : + PKT_TX_OUTER_IPV6; + ol_flags |= PKT_TX_TUNNEL_VXLAN; + mb->l2_len = + vnet_buffer (b)->l3_hdr_offset - vnet_buffer2 (b)->outer_l4_hdr_offset; + mb->l3_len = + vnet_buffer (b)->l4_hdr_offset - vnet_buffer (b)->l3_hdr_offset; + mb->outer_l2_len = + vnet_buffer2 (b)->outer_l3_hdr_offset - b->current_data; + mb->outer_l3_len = vnet_buffer2 (b)->outer_l4_hdr_offset - + vnet_buffer2 (b)->outer_l3_hdr_offset; + outer_hdr_len = mb->outer_l2_len + mb->outer_l3_len; + } + else + { + mb->l2_len = + vnet_buffer (b)->l3_hdr_offset - vnet_buffer (b)->l2_hdr_offset; + mb->l3_len = + vnet_buffer (b)->l4_hdr_offset - vnet_buffer (b)->l3_hdr_offset; + mb->outer_l2_len = 0; + mb->outer_l3_len = 0; + } + if (tso) { mb->l4_len = vnet_buffer2 (b)->gso_l4_hdr_sz; mb->tso_segsz = vnet_buffer2 (b)->gso_size; /* ensure packet is large enough to require tso */ - max_pkt_len = mb->l2_len + mb->l3_len + mb->l4_len + mb->tso_segsz; + max_pkt_len = + outer_hdr_len + mb->l2_len + mb->l3_len + mb->l4_len + mb->tso_segsz; if (mb->tso_segsz != 0 && mb->pkt_len > max_pkt_len) ol_flags |= (tcp_cksum ? PKT_TX_TCP_SEG : PKT_TX_UDP_SEG); } diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h index dd43137aebe..51f80a80462 100644 --- a/src/plugins/dpdk/device/dpdk.h +++ b/src/plugins/dpdk/device/dpdk.h @@ -304,6 +304,7 @@ typedef struct u8 no_multi_seg; u8 enable_lro; u8 enable_tcp_udp_checksum; + u8 enable_outer_checksum_offload; u8 no_tx_checksum_offload; u8 enable_telemetry; u16 max_simd_bitwidth; diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c index f7c1cc106ba..18124c32ff0 100644 --- a/src/plugins/dpdk/device/init.c +++ b/src/plugins/dpdk/device/init.c @@ -370,6 +370,18 @@ dpdk_lib_init (dpdk_main_t * dm) xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_UDP_CKSUM; if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_TCP_CKSUM; + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) + xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM; + + if (dm->conf->enable_outer_checksum_offload) + { + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) + xd->port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) + xd->port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_OUTER_UDP_CKSUM; + } } if (dm->conf->enable_lro) @@ -480,9 +492,8 @@ dpdk_lib_init (dpdk_main_t * dm) { xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM; xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM; - xd->flags |= - DPDK_DEVICE_FLAG_TX_OFFLOAD | - DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM; + xd->flags |= DPDK_DEVICE_FLAG_TX_OFFLOAD | + DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM; } xd->port_conf.intr_conf.rxq = 1; @@ -816,6 +827,11 @@ dpdk_lib_init (dpdk_main_t * dm) hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TX_IP4_CKSUM | VNET_HW_INTERFACE_CAP_SUPPORTS_TX_TCP_CKSUM | VNET_HW_INTERFACE_CAP_SUPPORTS_TX_UDP_CKSUM; + if (dm->conf->enable_outer_checksum_offload) + { + hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TX_IP4_OUTER_CKSUM | + VNET_HW_INTERFACE_CAP_SUPPORTS_TX_UDP_OUTER_CKSUM; + } } if (devconf->tso == DPDK_DEVICE_TSO_ON && hi != NULL) { @@ -823,10 +839,16 @@ dpdk_lib_init (dpdk_main_t * dm) if ((dm->conf->enable_tcp_udp_checksum) && (hi->caps & VNET_HW_INTERFACE_CAP_SUPPORTS_TX_CKSUM)) { - hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO | - VNET_HW_INTERFACE_CAP_SUPPORTS_UDP_GSO; - xd->port_conf.txmode.offloads |= - DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_UDP_TSO; + hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO; + xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_TSO; + + if (dm->conf->enable_outer_checksum_offload && + (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO)) + { + xd->port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_VXLAN_TNL_TSO; + hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_VXLAN_TNL_GSO; + } } else clib_warning ("%s: TCP/UDP checksum offload must be enabled", @@ -1391,8 +1413,11 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input) conf->enable_telemetry = 1; else if (unformat (input, "enable-tcp-udp-checksum")) - conf->enable_tcp_udp_checksum = 1; - + { + conf->enable_tcp_udp_checksum = 1; + if (unformat (input, "enable-outer-checksum-offload")) + conf->enable_outer_checksum_offload = 1; + } else if (unformat (input, "no-tx-checksum-offload")) conf->no_tx_checksum_offload = 1; -- cgit 1.2.3-korg