On 27 Aug 2024, at 15:30, Mike Pattrick wrote:
> On Tue, Aug 27, 2024 at 7:03 AM Eelco Chaudron <[email protected]> wrote: >> >> Hi Mike, >> >> Coverity reported a problem on this patch, see below. >> >> Can you take a look and sent a fix? >> >> Thanks, >> >> Eelco >> >> On 17 Jan 2024, at 20:26, Mike Pattrick wrote: >> >>> From: Dexia Li <[email protected]> >>> >>> For userspace datapath, this patch provides vxlan and geneve tunnel tso. >>> Only support userspace vxlan or geneve tunnel, meanwhile support >>> tunnel outter and inner csum offload. If netdev do not support offload >>> features, there is a software fallback.If netdev do not support vxlan >>> and geneve tso,packets will drop. Front-end devices can close offload >>> features by ethtool also. >>> >>> Signed-off-by: Dexia Li <[email protected]> >>> Co-authored-by: Mike Pattrick <[email protected]> >>> Signed-off-by: Mike Pattrick <[email protected]> >>> --- >>> v9: Rebased patch >>> v12: >>> - Sent in by Dexia >>> v13: >>> - Corrected formatting and comment/function naming consistency >>> - Double encapsulation with TSO will now drop packets >>> - Corrected packet leak condition. >>> --- >>> lib/dp-packet.c | 41 +++++++- >>> lib/dp-packet.h | 201 +++++++++++++++++++++++++++++++++++++--- >>> lib/dpif-netdev.c | 4 +- >>> lib/flow.c | 2 +- >>> lib/netdev-dpdk.c | 86 +++++++++++++++-- >>> lib/netdev-dummy.c | 2 +- >>> lib/netdev-native-tnl.c | 101 +++++++++++++++++++- >>> lib/netdev-provider.h | 4 + >>> lib/netdev.c | 53 +++++++++-- >>> lib/packets.c | 12 +-- >>> lib/packets.h | 6 +- >>> tests/dpif-netdev.at | 4 +- >>> 12 files changed, 462 insertions(+), 54 deletions(-) >>> >>> diff --git a/lib/dp-packet.c b/lib/dp-packet.c >>> index 920402369..e7738c37a 100644 >>> --- a/lib/dp-packet.c >>> +++ b/lib/dp-packet.c >>> @@ -546,16 +546,47 @@ dp_packet_compare_offsets(struct dp_packet *b1, >>> struct dp_packet *b2, >>> return true; >>> } >>> >>> +void >>> +dp_packet_tnl_outer_ol_send_prepare(struct dp_packet *p, >>> + uint64_t flags) >>> +{ >>> + if (dp_packet_hwol_is_outer_ipv4_cksum(p)) { >>> + if (!(flags & NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM)) { >>> + dp_packet_ip_set_header_csum(p, false); >>> + dp_packet_ol_set_ip_csum_good(p); >>> + dp_packet_hwol_reset_outer_ipv4_csum(p); >>> + } >>> + } >>> + >>> + if (!dp_packet_hwol_is_outer_udp_cksum(p)) { >>> + return; >>> + } >>> + >>> + if (!(flags & NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM)) { >>> + packet_udp_complete_csum(p, false); >>> + dp_packet_ol_set_l4_csum_good(p); >>> + dp_packet_hwol_reset_outer_udp_csum(p); >>> + } >>> +} >>> + >>> /* Checks if the packet 'p' is compatible with netdev_ol_flags 'flags' >>> * and if not, updates the packet with the software fall back. */ >>> void >>> dp_packet_ol_send_prepare(struct dp_packet *p, uint64_t flags) >>> { >>> + bool tnl_inner = false; >>> + >>> + if (dp_packet_hwol_is_tunnel_geneve(p) || >>> + dp_packet_hwol_is_tunnel_vxlan(p)) { >>> + dp_packet_tnl_outer_ol_send_prepare(p, flags); >>> + tnl_inner = true; >>> + } >>> + >>> if (dp_packet_hwol_tx_ip_csum(p)) { >>> if (dp_packet_ip_checksum_good(p)) { >>> dp_packet_hwol_reset_tx_ip_csum(p); >>> } else if (!(flags & NETDEV_TX_OFFLOAD_IPV4_CKSUM)) { >>> - dp_packet_ip_set_header_csum(p); >>> + dp_packet_ip_set_header_csum(p, tnl_inner); >>> dp_packet_ol_set_ip_csum_good(p); >>> dp_packet_hwol_reset_tx_ip_csum(p); >>> } >>> @@ -565,24 +596,24 @@ dp_packet_ol_send_prepare(struct dp_packet *p, >>> uint64_t flags) >>> return; >>> } >>> >>> - if (dp_packet_l4_checksum_good(p)) { >>> + if (dp_packet_l4_checksum_good(p) && !tnl_inner) { >>> dp_packet_hwol_reset_tx_l4_csum(p); >>> return; >>> } >>> >>> if (dp_packet_hwol_l4_is_tcp(p) >>> && !(flags & NETDEV_TX_OFFLOAD_TCP_CKSUM)) { >>> - packet_tcp_complete_csum(p); >>> + packet_tcp_complete_csum(p, tnl_inner); >>> dp_packet_ol_set_l4_csum_good(p); >>> dp_packet_hwol_reset_tx_l4_csum(p); >>> } else if (dp_packet_hwol_l4_is_udp(p) >>> && !(flags & NETDEV_TX_OFFLOAD_UDP_CKSUM)) { >>> - packet_udp_complete_csum(p); >>> + packet_udp_complete_csum(p, tnl_inner); >>> dp_packet_ol_set_l4_csum_good(p); >>> dp_packet_hwol_reset_tx_l4_csum(p); >>> } else if (!(flags & NETDEV_TX_OFFLOAD_SCTP_CKSUM) >>> && dp_packet_hwol_l4_is_sctp(p)) { >>> - packet_sctp_complete_csum(p); >>> + packet_sctp_complete_csum(p, tnl_inner); >>> dp_packet_ol_set_l4_csum_good(p); >>> dp_packet_hwol_reset_tx_l4_csum(p); >>> } >>> diff --git a/lib/dp-packet.h b/lib/dp-packet.h >>> index 11aa00723..c626acfbd 100644 >>> --- a/lib/dp-packet.h >>> +++ b/lib/dp-packet.h >>> @@ -86,22 +86,47 @@ enum dp_packet_offload_mask { >>> DEF_OL_FLAG(DP_PACKET_OL_TX_SCTP_CKSUM, RTE_MBUF_F_TX_SCTP_CKSUM, >>> 0x800), >>> /* Offload IP checksum. */ >>> DEF_OL_FLAG(DP_PACKET_OL_TX_IP_CKSUM, RTE_MBUF_F_TX_IP_CKSUM, 0x1000), >>> + /* Offload packet is tunnel GENEVE. */ >>> + DEF_OL_FLAG(DP_PACKET_OL_TX_TUNNEL_GENEVE, >>> + RTE_MBUF_F_TX_TUNNEL_GENEVE, 0x2000), >>> + /* Offload packet is tunnel VXLAN. */ >>> + DEF_OL_FLAG(DP_PACKET_OL_TX_TUNNEL_VXLAN, >>> + RTE_MBUF_F_TX_TUNNEL_VXLAN, 0x4000), >>> + /* Offload tunnel packet, out is IPv4 */ >>> + DEF_OL_FLAG(DP_PACKET_OL_TX_OUTER_IPV4, >>> + RTE_MBUF_F_TX_OUTER_IPV4, 0x8000), >>> + /* Offload tunnel out IPv4 checksum */ >>> + DEF_OL_FLAG(DP_PACKET_OL_TX_OUTER_IP_CKSUM, >>> + RTE_MBUF_F_TX_OUTER_IP_CKSUM, 0x10000), >>> + /* Offload tunnel out UDP checksum */ >>> + DEF_OL_FLAG(DP_PACKET_OL_TX_OUTER_UDP_CKSUM, >>> + RTE_MBUF_F_TX_OUTER_UDP_CKSUM, 0x20000), >>> + /* Offload tunnel packet, out is IPv6 */ >>> + DEF_OL_FLAG(DP_PACKET_OL_TX_OUTER_IPV6, >>> + RTE_MBUF_F_TX_OUTER_IPV6, 0x40000), >>> + >>> /* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */ >>> }; >>> >>> -#define DP_PACKET_OL_SUPPORTED_MASK (DP_PACKET_OL_RSS_HASH | \ >>> - DP_PACKET_OL_FLOW_MARK | \ >>> - DP_PACKET_OL_RX_L4_CKSUM_BAD | \ >>> - DP_PACKET_OL_RX_IP_CKSUM_BAD | \ >>> - DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ >>> - DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ >>> - DP_PACKET_OL_TX_TCP_SEG | \ >>> - DP_PACKET_OL_TX_IPV4 | \ >>> - DP_PACKET_OL_TX_IPV6 | \ >>> - DP_PACKET_OL_TX_TCP_CKSUM | \ >>> - DP_PACKET_OL_TX_UDP_CKSUM | \ >>> - DP_PACKET_OL_TX_SCTP_CKSUM | \ >>> - DP_PACKET_OL_TX_IP_CKSUM) >>> +#define DP_PACKET_OL_SUPPORTED_MASK (DP_PACKET_OL_RSS_HASH | \ >>> + DP_PACKET_OL_FLOW_MARK | \ >>> + DP_PACKET_OL_RX_L4_CKSUM_BAD | \ >>> + DP_PACKET_OL_RX_IP_CKSUM_BAD | \ >>> + DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ >>> + DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ >>> + DP_PACKET_OL_TX_TCP_SEG | \ >>> + DP_PACKET_OL_TX_IPV4 | \ >>> + DP_PACKET_OL_TX_IPV6 | \ >>> + DP_PACKET_OL_TX_TCP_CKSUM | \ >>> + DP_PACKET_OL_TX_UDP_CKSUM | \ >>> + DP_PACKET_OL_TX_SCTP_CKSUM | \ >>> + DP_PACKET_OL_TX_IP_CKSUM | \ >>> + DP_PACKET_OL_TX_TUNNEL_GENEVE | \ >>> + DP_PACKET_OL_TX_TUNNEL_VXLAN | \ >>> + DP_PACKET_OL_TX_OUTER_IPV4 | \ >>> + DP_PACKET_OL_TX_OUTER_IP_CKSUM | \ >>> + DP_PACKET_OL_TX_OUTER_UDP_CKSUM | \ >>> + DP_PACKET_OL_TX_OUTER_IPV6) >>> >>> #define DP_PACKET_OL_TX_L4_MASK (DP_PACKET_OL_TX_TCP_CKSUM | \ >>> DP_PACKET_OL_TX_UDP_CKSUM | \ >>> @@ -139,6 +164,10 @@ struct dp_packet { >>> * or UINT16_MAX. */ >>> uint16_t l4_ofs; /* Transport-level header offset, >>> or UINT16_MAX. */ >>> + uint16_t inner_l3_ofs; /* Inner Network-level header offset, >>> + * or UINT16_MAX. */ >>> + uint16_t inner_l4_ofs; /* Inner Transport-level header offset, >>> + or UINT16_MAX. */ >>> uint32_t cutlen; /* length in bytes to cut from the end. >>> */ >>> ovs_be32 packet_type; /* Packet type as defined in OpenFlow */ >>> uint16_t csum_start; /* Position to start checksumming from. >>> */ >>> @@ -250,6 +279,8 @@ bool dp_packet_compare_offsets(struct dp_packet *good, >>> struct dp_packet *test, >>> struct ds *err_str); >>> void dp_packet_ol_send_prepare(struct dp_packet *, uint64_t); >>> +void dp_packet_tnl_outer_ol_send_prepare(struct dp_packet *, uint64_t); >>> + >>> >>> >>> /* Frees memory that 'b' points to, as well as 'b' itself. */ >>> @@ -482,6 +513,22 @@ dp_packet_l4_size(const struct dp_packet *b) >>> : 0; >>> } >>> >>> +static inline void * >>> +dp_packet_inner_l3(const struct dp_packet *b) >>> +{ >>> + return b->inner_l3_ofs != UINT16_MAX >>> + ? (char *) dp_packet_data(b) + b->inner_l3_ofs >>> + : NULL; >>> +} >>> + >>> +static inline void * >>> +dp_packet_inner_l4(const struct dp_packet *b) >>> +{ >>> + return b->inner_l4_ofs != UINT16_MAX >>> + ? (char *) dp_packet_data(b) + b->inner_l4_ofs >>> + : NULL; >>> +} >>> + >>> static inline const void * >>> dp_packet_get_tcp_payload(const struct dp_packet *b) >>> { >>> @@ -539,6 +586,25 @@ dp_packet_get_nd_payload(const struct dp_packet *b) >>> } >>> >>> #ifdef DPDK_NETDEV >>> +static inline void >>> +dp_packet_set_l2_len(struct dp_packet *b, size_t l2_len) >>> +{ >>> + b->mbuf.l2_len = l2_len; >>> +} >>> + >>> +static inline void >>> +dp_packet_set_l3_len(struct dp_packet *b, size_t l3_len) >>> +{ >>> + b->mbuf.l3_len = l3_len; >>> +} >>> + >>> +static inline void >>> +dp_packet_set_l4_len(struct dp_packet *b, size_t l4_len) >>> +{ >>> + b->mbuf.l4_len = l4_len; >>> +} >>> + >>> + >>> static inline uint64_t * >>> dp_packet_ol_flags_ptr(const struct dp_packet *b) >>> { >>> @@ -558,6 +624,24 @@ dp_packet_flow_mark_ptr(const struct dp_packet *b) >>> } >>> >>> #else >>> +static inline void >>> +dp_packet_set_l2_len(struct dp_packet *b OVS_UNUSED, size_t l2_len >>> OVS_UNUSED) >>> +{ >>> + /* There is no implementation. */ >>> +} >>> + >>> +static inline void >>> +dp_packet_set_l3_len(struct dp_packet *b OVS_UNUSED, size_t l3_len >>> OVS_UNUSED) >>> +{ >>> + /* There is no implementation. */ >>> +} >>> + >>> +static inline void >>> +dp_packet_set_l4_len(struct dp_packet *b OVS_UNUSED, size_t l4_len >>> OVS_UNUSED) >>> +{ >>> + /* There is no implementation. */ >>> +} >>> + >>> static inline uint32_t * >>> dp_packet_ol_flags_ptr(const struct dp_packet *b) >>> { >>> @@ -619,6 +703,8 @@ dp_packet_set_size(struct dp_packet *b, uint32_t v) >>> * (and thus 'v') will always be <= UINT16_MAX; this means that there >>> is no >>> * loss of accuracy in assigning 'v' to 'data_len'. >>> */ >>> + >>> + ovs_assert(v <= UINT16_MAX); >>> b->mbuf.data_len = (uint16_t)v; /* Current seg length. */ >>> b->mbuf.pkt_len = v; /* Total length of all segments >>> linked to >>> * this segment. */ >>> @@ -1056,6 +1142,36 @@ dp_packet_hwol_l4_is_sctp(struct dp_packet *b) >>> DP_PACKET_OL_TX_SCTP_CKSUM; >>> } >>> >>> +/* Returns 'true' if packet 'b' is marked for tunnel GENEVE >>> + * checksum offloading. */ >>> +static inline bool >>> +dp_packet_hwol_is_tunnel_geneve(struct dp_packet *b) >>> +{ >>> + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TUNNEL_GENEVE); >>> +} >>> + >>> +/* Returns 'true' if packet 'b' is marked for tunnel VXLAN >>> + * checksum offloading. */ >>> +static inline bool >>> +dp_packet_hwol_is_tunnel_vxlan(struct dp_packet *b) >>> +{ >>> + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TUNNEL_VXLAN); >>> +} >>> + >>> +/* Returns 'true' if packet 'b' is marked for outer IPv4 checksum offload. >>> */ >>> +static inline bool >>> +dp_packet_hwol_is_outer_ipv4_cksum(struct dp_packet *b) >>> +{ >>> + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_OUTER_IP_CKSUM); >>> +} >>> + >>> +/* Returns 'true' if packet 'b' is marked for outer UDP checksum offload. >>> */ >>> +static inline bool >>> +dp_packet_hwol_is_outer_udp_cksum(struct dp_packet *b) >>> +{ >>> + return !!(*dp_packet_ol_flags_ptr(b) & >>> DP_PACKET_OL_TX_OUTER_UDP_CKSUM); >>> +} >>> + >>> static inline void >>> dp_packet_hwol_reset_tx_l4_csum(struct dp_packet *p) >>> { >>> @@ -1078,6 +1194,14 @@ dp_packet_hwol_set_tx_ipv6(struct dp_packet *a) >>> *dp_packet_ol_flags_ptr(a) |= DP_PACKET_OL_TX_IPV6; >>> } >>> >>> +/* Mark packet 'a' as a tunnel packet with outer IPv6 header. */ >>> +static inline void >>> +dp_packet_hwol_set_tx_outer_ipv6(struct dp_packet *a) >>> +{ >>> + *dp_packet_ol_flags_ptr(a) &= ~DP_PACKET_OL_TX_OUTER_IPV4; >>> + *dp_packet_ol_flags_ptr(a) |= DP_PACKET_OL_TX_OUTER_IPV6; >>> +} >>> + >>> /* Returns 'true' if packet 'p' is marked for IPv4 checksum offloading. */ >>> static inline bool >>> dp_packet_hwol_tx_ip_csum(const struct dp_packet *p) >>> @@ -1131,6 +1255,53 @@ dp_packet_hwol_set_tcp_seg(struct dp_packet *b) >>> *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_SEG; >>> } >>> >>> +/* Mark packet 'b' for tunnel GENEVE offloading. */ >>> +static inline void >>> +dp_packet_hwol_set_tunnel_geneve(struct dp_packet *b) >>> +{ >>> + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TUNNEL_GENEVE; >>> +} >>> + >>> +/* Mark packet 'b' for tunnel VXLAN offloading. */ >>> +static inline void >>> +dp_packet_hwol_set_tunnel_vxlan(struct dp_packet *b) >>> +{ >>> + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TUNNEL_VXLAN; >>> +} >>> + >>> +/* Mark packet 'b' for out IPv4 packet. */ >>> +static inline void >>> +dp_packet_hwol_set_tx_outer_ipv4(struct dp_packet *b) >>> +{ >>> + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_OUTER_IPV4; >>> +} >>> + >>> +/* Mark packet 'b' for out IPv4 csum offloading. */ >>> +static inline void >>> +dp_packet_hwol_set_tx_outer_ipv4_csum(struct dp_packet *b) >>> +{ >>> + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_OUTER_IP_CKSUM; >>> +} >>> + >>> +static inline void >>> +dp_packet_hwol_reset_outer_ipv4_csum(struct dp_packet *p) >>> +{ >>> + *dp_packet_ol_flags_ptr(p) &= ~DP_PACKET_OL_TX_OUTER_IP_CKSUM; >>> +} >>> + >>> +static inline void >>> +dp_packet_hwol_reset_outer_udp_csum(struct dp_packet *p) >>> +{ >>> + *dp_packet_ol_flags_ptr(p) &= ~DP_PACKET_OL_TX_OUTER_UDP_CKSUM; >>> +} >>> + >>> +/* Mark packet 'b' for out UDP csum offloading. */ >>> +static inline void >>> +dp_packet_hwol_set_outer_udp_csum(struct dp_packet *b) >>> +{ >>> + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_OUTER_UDP_CKSUM; >>> +} >>> + >>> /* Resets TCP Segmentation flag in packet 'p'. */ >>> static inline void >>> dp_packet_hwol_reset_tcp_seg(struct dp_packet *p) >>> @@ -1172,9 +1343,9 @@ dp_packet_ip_checksum_bad(const struct dp_packet *p) >>> >>> /* Calculate and set the IPv4 header checksum in packet 'p'. */ >>> static inline void >>> -dp_packet_ip_set_header_csum(struct dp_packet *p) >>> +dp_packet_ip_set_header_csum(struct dp_packet *p, bool inner) >>> { >>> - struct ip_header *ip = dp_packet_l3(p); >>> + struct ip_header *ip = (inner) ? dp_packet_inner_l3(p) : >>> dp_packet_l3(p); >>> >>> ovs_assert(ip); >>> ip->ip_csum = 0; >>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >>> index df5bbf85a..c1981137f 100644 >>> --- a/lib/dpif-netdev.c >>> +++ b/lib/dpif-netdev.c >>> @@ -8194,7 +8194,9 @@ dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, >>> struct dp_packet *packet_, >>> ds_destroy(&ds); >>> } >>> >>> - dp_packet_ol_send_prepare(packet_, 0); >>> + if (type != DPIF_UC_MISS) { >>> + dp_packet_ol_send_prepare(packet_, 0); >>> + } >>> >>> return dp->upcall_cb(packet_, flow, ufid, pmd->core_id, type, userdata, >>> actions, wc, put_actions, dp->upcall_aux); >>> diff --git a/lib/flow.c b/lib/flow.c >>> index b8f99f66b..82d93570a 100644 >>> --- a/lib/flow.c >>> +++ b/lib/flow.c >>> @@ -3278,7 +3278,7 @@ packet_expand(struct dp_packet *p, const struct flow >>> *flow, size_t size) >>> if (dp_packet_hwol_tx_ip_csum(p)) { >>> dp_packet_ol_reset_ip_csum_good(p); >>> } else { >>> - dp_packet_ip_set_header_csum(p); >>> + dp_packet_ip_set_header_csum(p, false); >>> dp_packet_ol_set_ip_csum_good(p); >>> } >>> pseudo_hdr_csum = packet_csum_pseudoheader(ip); >>> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c >>> index 1ff25c246..fb26825ff 100644 >>> --- a/lib/netdev-dpdk.c >>> +++ b/lib/netdev-dpdk.c >>> @@ -416,6 +416,10 @@ enum dpdk_hw_ol_features { >>> NETDEV_TX_UDP_CKSUM_OFFLOAD = 1 << 5, >>> NETDEV_TX_SCTP_CKSUM_OFFLOAD = 1 << 6, >>> NETDEV_TX_TSO_OFFLOAD = 1 << 7, >>> + NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD = 1 << 8, >>> + NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD = 1 << 9, >>> + NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD = 1 << 10, >>> + NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD = 1 << 11, >>> }; >>> >>> enum dpdk_rx_steer_flags { >>> @@ -1075,6 +1079,14 @@ netdev_dpdk_update_netdev_flags(struct netdev_dpdk >>> *dev) >>> NETDEV_TX_OFFLOAD_SCTP_CKSUM); >>> netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_TSO_OFFLOAD, >>> NETDEV_TX_OFFLOAD_TCP_TSO); >>> + netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD, >>> + NETDEV_TX_VXLAN_TNL_TSO); >>> + netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD, >>> + NETDEV_TX_GENEVE_TNL_TSO); >>> + netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD, >>> + NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM); >>> + netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD, >>> + NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM); >>> } >>> >>> static int >>> @@ -1129,6 +1141,22 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev, >>> int n_rxq, int n_txq) >>> conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO; >>> } >>> >>> + if (dev->hw_ol_features & NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD) { >>> + conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO; >>> + } >>> + >>> + if (dev->hw_ol_features & NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD) { >>> + conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO; >>> + } >>> + >>> + if (dev->hw_ol_features & NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD) { >>> + conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM; >>> + } >>> + >>> + if (dev->hw_ol_features & NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD) { >>> + conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM; >>> + } >>> + >>> /* Limit configured rss hash functions to only those supported >>> * by the eth device. */ >>> conf.rx_adv_conf.rss_conf.rss_hf &= info.flow_type_rss_offloads; >>> @@ -1346,6 +1374,18 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev) >>> dev->hw_ol_features &= ~NETDEV_TX_SCTP_CKSUM_OFFLOAD; >>> } >>> >>> + if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM) { >>> + dev->hw_ol_features |= NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD; >>> + } else { >>> + dev->hw_ol_features &= ~NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD; >>> + } >>> + >>> + if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) { >>> + dev->hw_ol_features |= NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD; >>> + } else { >>> + dev->hw_ol_features &= ~NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD; >>> + } >>> + >>> dev->hw_ol_features &= ~NETDEV_TX_TSO_OFFLOAD; >>> if (userspace_tso_enabled()) { >>> if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_TCP_TSO) { >>> @@ -1354,6 +1394,20 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev) >>> VLOG_WARN("%s: Tx TSO offload is not supported.", >>> netdev_get_name(&dev->up)); >>> } >>> + >>> + if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) { >>> + dev->hw_ol_features |= NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD; >>> + } else { >>> + VLOG_WARN("%s: Tx Vxlan tunnel TSO offload is not supported.", >>> + netdev_get_name(&dev->up)); >>> + } >>> + >>> + if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO) { >>> + dev->hw_ol_features |= NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD; >>> + } else { >>> + VLOG_WARN("%s: Tx Geneve tunnel TSO offload is not supported.", >>> + netdev_get_name(&dev->up)); >>> + } >>> } >>> >>> n_rxq = MIN(info.max_rx_queues, dev->up.n_rxq); >>> @@ -2479,11 +2533,23 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk >>> *dev, struct rte_mbuf *mbuf) >>> return true; >>> } >>> >>> - mbuf->l2_len = (char *) dp_packet_l3(pkt) - (char *) >>> dp_packet_eth(pkt); >>> - mbuf->l3_len = (char *) dp_packet_l4(pkt) - (char *) dp_packet_l3(pkt); >>> - mbuf->l4_len = 0; >>> - mbuf->outer_l2_len = 0; >>> - mbuf->outer_l3_len = 0; >>> + /* If packet is vxlan or geneve tunnel packet, calculate outer >>> + * l2 len and outer l3 len. Inner l2/l3/l4 len are calculated >>> + * before. */ >>> + if (mbuf->ol_flags & >>> + (RTE_MBUF_F_TX_TUNNEL_GENEVE | RTE_MBUF_F_TX_TUNNEL_VXLAN)) { >>> + mbuf->outer_l2_len = (char *) dp_packet_l3(pkt) - >>> + (char *) dp_packet_eth(pkt); >>> + mbuf->outer_l3_len = (char *) dp_packet_l4(pkt) - >>> + (char *) dp_packet_l3(pkt); >>> + } else { >>> + mbuf->l2_len = (char *) dp_packet_l3(pkt) - >>> + (char *) dp_packet_eth(pkt); >>> + mbuf->l3_len = (char *) dp_packet_l4(pkt) - >>> + (char *) dp_packet_l3(pkt); >>> + mbuf->outer_l2_len = 0; >>> + mbuf->outer_l3_len = 0; >>> + } >>> th = dp_packet_l4(pkt); >>> >>> if (mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) { >>> @@ -2501,8 +2567,14 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk >>> *dev, struct rte_mbuf *mbuf) >>> return false; >>> } >>> >>> - mbuf->l4_len = TCP_OFFSET(th->tcp_ctl) * 4; >>> - mbuf->tso_segsz = dev->mtu - mbuf->l3_len - mbuf->l4_len; >>> + if (mbuf->ol_flags & (RTE_MBUF_F_TX_TUNNEL_GENEVE | >>> + RTE_MBUF_F_TX_TUNNEL_VXLAN)) { >>> + mbuf->tso_segsz = dev->mtu - mbuf->l2_len - mbuf->l3_len - >>> + mbuf->l4_len - mbuf->outer_l3_len; >>> + } else { >>> + mbuf->l4_len = TCP_OFFSET(th->tcp_ctl) * 4; >>> + mbuf->tso_segsz = dev->mtu - mbuf->l3_len - mbuf->l4_len; >>> + } >>> >>> if (mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) { >>> int hdr_len = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len; >>> diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c >>> index 8c6e6d448..21db9edb5 100644 >>> --- a/lib/netdev-dummy.c >>> +++ b/lib/netdev-dummy.c >>> @@ -1202,7 +1202,7 @@ netdev_dummy_send(struct netdev *netdev, int qid, >>> >>> if (dp_packet_hwol_tx_ip_csum(packet) && >>> !dp_packet_ip_checksum_good(packet)) { >>> - dp_packet_ip_set_header_csum(packet); >>> + dp_packet_ip_set_header_csum(packet, false); >>> dp_packet_ol_set_ip_csum_good(packet); >>> } >>> >>> diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c >>> index a0682c70f..fa87c6281 100644 >>> --- a/lib/netdev-native-tnl.c >>> +++ b/lib/netdev-native-tnl.c >>> @@ -173,15 +173,29 @@ netdev_tnl_push_ip_header(struct dp_packet *packet, >>> const void *header, >>> ip6->ip6_plen = htons(*ip_tot_size); >>> packet_set_ipv6_flow_label(&ip6->ip6_flow, ipv6_label); >>> packet->l4_ofs = dp_packet_size(packet) - *ip_tot_size; >>> - dp_packet_hwol_set_tx_ipv6(packet); >>> + >>> + if (dp_packet_hwol_is_tunnel_geneve(packet) || >>> + dp_packet_hwol_is_tunnel_vxlan(packet)) { >>> + dp_packet_hwol_set_tx_outer_ipv6(packet); >>> + } else { >>> + dp_packet_hwol_set_tx_ipv6(packet); >>> + } >>> + >>> dp_packet_ol_reset_ip_csum_good(packet); >>> return ip6 + 1; >>> } else { >>> ip = netdev_tnl_ip_hdr(eth); >>> ip->ip_tot_len = htons(*ip_tot_size); >>> /* Postpone checksum to when the packet is pushed to the port. */ >>> - dp_packet_hwol_set_tx_ipv4(packet); >>> - dp_packet_hwol_set_tx_ip_csum(packet); >>> + if (dp_packet_hwol_is_tunnel_geneve(packet) || >>> + dp_packet_hwol_is_tunnel_vxlan(packet)) { >>> + dp_packet_hwol_set_tx_outer_ipv4(packet); >>> + dp_packet_hwol_set_tx_outer_ipv4_csum(packet); >>> + } else { >>> + dp_packet_hwol_set_tx_ipv4(packet); >>> + dp_packet_hwol_set_tx_ip_csum(packet); >>> + } >>> + >>> dp_packet_ol_reset_ip_csum_good(packet); >>> *ip_tot_size -= IP_HEADER_LEN; >>> packet->l4_ofs = dp_packet_size(packet) - *ip_tot_size; >>> @@ -226,6 +240,74 @@ udp_extract_tnl_md(struct dp_packet *packet, struct >>> flow_tnl *tnl, >>> return udp + 1; >>> } >>> >>> +/* Calculate inner l2 l3 l4 len as tunnel outer header is not >>> + * encapsulated now. */ >>> +static void >>> +dp_packet_tnl_ol_process(struct dp_packet *packet, >>> + const struct ovs_action_push_tnl *data) >>> +{ >>> + struct udp_header *udp = NULL; >>> + uint8_t opt_len = 0; >>> + struct eth_header *eth = NULL; >>> + struct ip_header *ip = NULL; >>> + struct genevehdr *gnh = NULL; >>> + >>> + /* l2 l3 l4 len refer to inner len, tunnel outer >>> + * header is not encapsulated here. */ >>> + if (dp_packet_hwol_l4_mask(packet)) { >>> + ip = dp_packet_l3(packet); >>> + >>> + if (ip->ip_proto == IPPROTO_TCP) { >>> + struct tcp_header *th = dp_packet_l4(packet); >>> + dp_packet_set_l4_len(packet, TCP_OFFSET(th->tcp_ctl) * 4); >>> + } else if (ip->ip_proto == IPPROTO_UDP) { >>> + dp_packet_set_l4_len(packet, UDP_HEADER_LEN); >>> + } else if (ip->ip_proto == IPPROTO_SCTP) { >>> + dp_packet_set_l4_len(packet, SCTP_HEADER_LEN); >>> + } >>> + >>> + dp_packet_set_l3_len(packet, (char *) dp_packet_l4(packet) - >>> + (char *) dp_packet_l3(packet)); >>> + >>> + if (data->tnl_type == OVS_VPORT_TYPE_GENEVE || >>> + data->tnl_type == OVS_VPORT_TYPE_VXLAN) { >>> + >>> + if (IP_VER(ip->ip_ihl_ver) == 4) { >>> + dp_packet_hwol_set_tx_ipv4(packet); >>> + dp_packet_hwol_tx_ip_csum(packet); >> >> CID 425094: (#1 of 1): Unchecked return value (CHECKED_RETURN) >> 4. check_return: Calling dp_packet_hwol_tx_ip_csum without checking return >> value (as is done elsewhere 9 out of 11 times). >> >> I guess this needs to be dp_packet_hwol_set_tx_ip_csum()? > > Seems right, I'll send a patch. Interestingly it says "as is done > elsewhere 9 out of 11 times". I see the other 10 uses, but it does > seem to be checked. Thanks, and same here, I could not find the other issue. //Eelco > > lib/netdev-dummy.c > 1232: if (dp_packet_hwol_tx_ip_csum(packet) && > > lib/dp-packet.h > 1378: return dp_packet_hwol_tx_ip_csum(b) && > 1394: return dp_packet_hwol_tx_ip_csum(b); > > lib/odp-execute.c > 174: if (dp_packet_hwol_tx_ip_csum(packet)) { > 190: if (dp_packet_hwol_tx_ip_csum(packet)) { > > lib/ipf.c > 436: if (dp_packet_hwol_tx_ip_csum(pkt)) { > 1211: if (dp_packet_hwol_tx_ip_csum(frag_i->pkt)) { > > lib/dp-packet.c > 609: if (dp_packet_hwol_tx_ip_csum(p)) { > > lib/conntrack.c > 3509: if (dp_packet_hwol_tx_ip_csum(pkt)) { > > lib/flow.c > 3273: if (dp_packet_hwol_tx_ip_csum(p)) { > > > Does it say what the other one is? > > Thanks, > M > >> >>> + } else if (IP_VER(ip->ip_ihl_ver) == 6) { >>> + dp_packet_hwol_set_tx_ipv6(packet); >>> + } >>> + } >>> + >>> + /* Attention please, tunnel inner l2 len is consist of udp header >>> + * len and tunnel header len and inner l2 len. */ >>> + if (data->tnl_type == OVS_VPORT_TYPE_GENEVE) { >>> + eth = (struct eth_header *)(data->header); >>> + ip = (struct ip_header *)(eth + 1); >>> + udp = (struct udp_header *)(ip + 1); >>> + gnh = (struct genevehdr *)(udp + 1); >>> + opt_len = gnh->opt_len * 4; >>> + dp_packet_hwol_set_tunnel_geneve(packet); >>> + dp_packet_set_l2_len(packet, (char *) dp_packet_l3(packet) - >>> + (char *) dp_packet_eth(packet) + >>> + GENEVE_BASE_HLEN + opt_len); >>> + >>> + packet->inner_l3_ofs = packet->l3_ofs + GENEVE_BASE_HLEN + >>> opt_len; >>> + packet->inner_l4_ofs = packet->l4_ofs + GENEVE_BASE_HLEN + >>> opt_len; >>> + >>> + } else if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) { >>> + dp_packet_hwol_set_tunnel_vxlan(packet); >>> + dp_packet_set_l2_len(packet, (char *) dp_packet_l3(packet) - >>> + (char *) dp_packet_eth(packet) + >>> + VXLAN_HLEN); >>> + >>> + packet->inner_l3_ofs = packet->l3_ofs + VXLAN_HLEN; >>> + packet->inner_l4_ofs = packet->l4_ofs + VXLAN_HLEN; >>> + } >>> + } >>> +} >>> + >>> void >>> netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED, >>> struct dp_packet *packet, >>> @@ -234,6 +316,7 @@ netdev_tnl_push_udp_header(const struct netdev *netdev >>> OVS_UNUSED, >>> struct udp_header *udp; >>> int ip_tot_size; >>> >>> + dp_packet_tnl_ol_process(packet, data); >>> udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len, >>> &ip_tot_size, 0); >>> >>> @@ -241,13 +324,21 @@ netdev_tnl_push_udp_header(const struct netdev >>> *netdev OVS_UNUSED, >>> udp->udp_src = netdev_tnl_get_src_port(packet); >>> udp->udp_len = htons(ip_tot_size); >>> >>> - /* Postpone checksum to the egress netdev. */ >>> - dp_packet_hwol_set_csum_udp(packet); >>> if (udp->udp_csum) { >>> dp_packet_ol_reset_l4_csum_good(packet); >>> + if (dp_packet_hwol_is_tunnel_geneve(packet) || >>> + dp_packet_hwol_is_tunnel_vxlan(packet)) { >>> + dp_packet_hwol_set_outer_udp_csum(packet); >>> + } else { >>> + dp_packet_hwol_set_csum_udp(packet); >>> + } >>> } else { >>> dp_packet_ol_set_l4_csum_good(packet); >>> } >>> + >>> + packet->inner_l3_ofs += packet->l4_ofs; >>> + packet->inner_l4_ofs += packet->l4_ofs; >>> + >>> } >>> >>> static void * >>> diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h >>> index a7393c7ce..22840a058 100644 >>> --- a/lib/netdev-provider.h >>> +++ b/lib/netdev-provider.h >>> @@ -43,6 +43,10 @@ enum netdev_ol_flags { >>> NETDEV_TX_OFFLOAD_UDP_CKSUM = 1 << 2, >>> NETDEV_TX_OFFLOAD_SCTP_CKSUM = 1 << 3, >>> NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 4, >>> + NETDEV_TX_VXLAN_TNL_TSO = 1 << 5, >>> + NETDEV_TX_GENEVE_TNL_TSO = 1 << 6, >>> + NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM = 1 << 7, >>> + NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM = 1 << 8, >>> }; >>> >>> /* A network device (e.g. an Ethernet device). >>> diff --git a/lib/netdev.c b/lib/netdev.c >>> index 3ed8049f7..cc2bdbcd2 100644 >>> --- a/lib/netdev.c >>> +++ b/lib/netdev.c >>> @@ -69,6 +69,8 @@ COVERAGE_DEFINE(netdev_received); >>> COVERAGE_DEFINE(netdev_sent); >>> COVERAGE_DEFINE(netdev_add_router); >>> COVERAGE_DEFINE(netdev_get_stats); >>> +COVERAGE_DEFINE(netdev_vxlan_tso_drops); >>> +COVERAGE_DEFINE(netdev_geneve_tso_drops); >>> COVERAGE_DEFINE(netdev_push_header_drops); >>> COVERAGE_DEFINE(netdev_soft_seg_good); >>> COVERAGE_DEFINE(netdev_soft_seg_drops); >>> @@ -912,6 +914,23 @@ netdev_send(struct netdev *netdev, int qid, struct >>> dp_packet_batch *batch, >>> !(netdev_flags & NETDEV_TX_OFFLOAD_TCP_TSO)) { >>> DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { >>> if (dp_packet_hwol_is_tso(packet)) { >>> + if (dp_packet_hwol_is_tunnel_vxlan(packet) >>> + && !(netdev_flags & NETDEV_TX_VXLAN_TNL_TSO)) { >>> + VLOG_ERR_RL(&rl, "%s: No VXLAN TSO support", >>> + netdev_get_name(netdev)); >>> + COVERAGE_INC(netdev_vxlan_tso_drops); >>> + dp_packet_delete_batch(batch, true); >>> + return false; >>> + } >>> + >>> + if (dp_packet_hwol_is_tunnel_geneve(packet) >>> + && !(netdev_flags & NETDEV_TX_GENEVE_TNL_TSO)) { >>> + VLOG_ERR_RL(&rl, "%s: No GENEVE TSO support", >>> + netdev_get_name(netdev)); >>> + COVERAGE_INC(netdev_geneve_tso_drops); >>> + dp_packet_delete_batch(batch, true); >>> + return false; >>> + } >>> return netdev_send_tso(netdev, qid, batch, concurrent_txq); >>> } >>> } >>> @@ -990,17 +1009,31 @@ netdev_push_header(const struct netdev *netdev, >>> size_t i, size = dp_packet_batch_size(batch); >>> >>> DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) { >>> - if (OVS_UNLIKELY(dp_packet_hwol_is_tso(packet))) { >>> + if (OVS_UNLIKELY(data->tnl_type != OVS_VPORT_TYPE_GENEVE && >>> + data->tnl_type != OVS_VPORT_TYPE_VXLAN && >>> + dp_packet_hwol_is_tso(packet))) { >>> COVERAGE_INC(netdev_push_header_drops); >>> dp_packet_delete(packet); >>> - VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is " >>> - "not supported: packet dropped", >>> - netdev_get_name(netdev)); >>> + VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not " >>> + "supported for %s tunnels: packet dropped", >>> + netdev_get_name(netdev), netdev_get_type(netdev)); >>> } else { >>> - /* The packet is going to be encapsulated and there is >>> - * no support yet for inner network header csum offloading. */ >>> - dp_packet_ol_send_prepare(packet, 0); >>> - >>> + if (data->tnl_type != OVS_VPORT_TYPE_GENEVE && >>> + data->tnl_type != OVS_VPORT_TYPE_VXLAN) { >>> + dp_packet_ol_send_prepare(packet, 0); >>> + } else if (dp_packet_hwol_is_tunnel_geneve(packet) || >>> + dp_packet_hwol_is_tunnel_vxlan(packet)) { >>> + if (dp_packet_hwol_is_tso(packet)) { >>> + COVERAGE_INC(netdev_push_header_drops); >>> + dp_packet_delete(packet); >>> + VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is >>> not " >>> + "supported with multiple levels of " >>> + "VXLAN or GENEVE encapsulation.", >>> + netdev_get_name(netdev)); >>> + continue; >>> + } >>> + dp_packet_ol_send_prepare(packet, 0); >>> + } >>> netdev->netdev_class->push_header(netdev, packet, data); >>> >>> pkt_metadata_init(&packet->md, data->out_port); >>> @@ -1446,6 +1479,10 @@ netdev_get_status(const struct netdev *netdev, >>> struct smap *smap) >>> 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); >>> + OL_ADD_STAT("vxlan_tso", NETDEV_TX_VXLAN_TNL_TSO); >>> + OL_ADD_STAT("geneve_tso", NETDEV_TX_GENEVE_TNL_TSO); >>> + OL_ADD_STAT("out_ip_csum", NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM); >>> + OL_ADD_STAT("out_udp_csum", NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM); >>> #undef OL_ADD_STAT >>> >>> err = 0; >>> diff --git a/lib/packets.c b/lib/packets.c >>> index dab823ba2..d9e41346e 100644 >>> --- a/lib/packets.c >>> +++ b/lib/packets.c >>> @@ -1997,9 +1997,9 @@ IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6) >>> /* Set TCP checksum field in packet 'p' with complete checksum. >>> * The packet must have the L3 and L4 offsets. */ >>> void >>> -packet_tcp_complete_csum(struct dp_packet *p) >>> +packet_tcp_complete_csum(struct dp_packet *p, bool inner) >>> { >>> - struct tcp_header *tcp = dp_packet_l4(p); >>> + struct tcp_header *tcp = (inner) ? dp_packet_inner_l4(p) : >>> dp_packet_l4(p); >>> >>> tcp->tcp_csum = 0; >>> if (dp_packet_hwol_is_ipv4(p)) { >>> @@ -2020,9 +2020,9 @@ packet_tcp_complete_csum(struct dp_packet *p) >>> /* Set UDP checksum field in packet 'p' with complete checksum. >>> * The packet must have the L3 and L4 offsets. */ >>> void >>> -packet_udp_complete_csum(struct dp_packet *p) >>> +packet_udp_complete_csum(struct dp_packet *p, bool inner) >>> { >>> - struct udp_header *udp = dp_packet_l4(p); >>> + struct udp_header *udp = (inner) ? dp_packet_inner_l4(p) : >>> dp_packet_l4(p); >>> >>> /* Skip csum calculation if the udp_csum is zero. */ >>> if (!udp->udp_csum) { >>> @@ -2052,9 +2052,9 @@ packet_udp_complete_csum(struct dp_packet *p) >>> /* Set SCTP checksum field in packet 'p' with complete checksum. >>> * The packet must have the L3 and L4 offsets. */ >>> void >>> -packet_sctp_complete_csum(struct dp_packet *p) >>> +packet_sctp_complete_csum(struct dp_packet *p, bool inner) >>> { >>> - struct sctp_header *sh = dp_packet_l4(p); >>> + struct sctp_header *sh = (inner) ? dp_packet_inner_l4(p) : >>> dp_packet_l4(p); >>> uint16_t tp_len = dp_packet_l4_size(p); >>> ovs_be32 csum; >>> >>> diff --git a/lib/packets.h b/lib/packets.h >>> index 12245b764..8b6994809 100644 >>> --- a/lib/packets.h >>> +++ b/lib/packets.h >>> @@ -1682,9 +1682,9 @@ uint32_t packet_csum_pseudoheader(const struct >>> ip_header *); >>> bool packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr, >>> bool *first_frag); >>> void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6); >>> -void packet_tcp_complete_csum(struct dp_packet *); >>> -void packet_udp_complete_csum(struct dp_packet *); >>> -void packet_sctp_complete_csum(struct dp_packet *); >>> +void packet_tcp_complete_csum(struct dp_packet *, bool is_inner); >>> +void packet_udp_complete_csum(struct dp_packet *, bool is_inner); >>> +void packet_sctp_complete_csum(struct dp_packet *, bool is_inner); >>> >>> #define DNS_HEADER_LEN 12 >>> struct dns_header { >>> diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at >>> index c9474af0a..24c24207b 100644 >>> --- a/tests/dpif-netdev.at >>> +++ b/tests/dpif-netdev.at >>> @@ -658,11 +658,11 @@ OVS_VSWITCHD_START( >>> other-config:datapath-id=1234 fail-mode=secure]) >>> >>> AT_CHECK([ovs-vsctl get interface p1 status | sed -n >>> 's/^{\(.*\).*}$/\1/p'], [0], [dnl >>> -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" >>> +tx_geneve_tso_offload="false", tx_ip_csum_offload="false", >>> tx_out_ip_csum_offload="false", tx_out_udp_csum_offload="false", >>> tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", >>> tx_tcp_seg_offload="false", tx_udp_csum_offload="false", >>> tx_vxlan_tso_offload="false" >>> ], []) >>> >>> AT_CHECK([ovs-vsctl get interface br0 status | sed -n >>> 's/^{\(.*\).*}$/\1/p'], [0], [dnl >>> -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" >>> +tx_geneve_tso_offload="false", tx_ip_csum_offload="false", >>> tx_out_ip_csum_offload="false", tx_out_udp_csum_offload="false", >>> tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", >>> tx_tcp_seg_offload="false", tx_udp_csum_offload="false", >>> tx_vxlan_tso_offload="false" >>> ], []) >>> >>> OVS_VSWITCHD_STOP >>> -- >>> 2.39.3 >>> >>> >>> _______________________________________________ >>> dev mailing list >>> [email protected] >>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
