On Sun, Oct 29, 2023 at 9:59 PM Dexia Li <[email protected]> wrote: > > > > -----邮件原件----- > 发件人: Mike Pattrick <[email protected]> > 发送时间: 2023年10月27日 23:04 > 收件人: Dexia Li <[email protected]> > 抄送: [email protected] > 主题: Re: [ovs-dev] [PATCH v5] userspace: Support vxlan and geneve tso. > > On Thu, Oct 26, 2023 at 3:40 AM Dexia Li via dev <[email protected]> > wrote: > > > > 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]> > > --- > > lib/dp-packet.c | 41 +++++++- > > lib/dp-packet.h | 216 ++++++++++++++++++++++++++++++++++++---- > > lib/dpif-netdev.c | 4 +- > > lib/flow.c | 2 +- > > lib/netdev-dpdk.c | 88 ++++++++++++++-- > > lib/netdev-dummy.c | 2 +- > > lib/netdev-native-tnl.c | 106 ++++++++++++++++++-- > > lib/netdev-provider.h | 4 + > > lib/netdev.c | 35 +++++-- > > lib/packets.c | 12 +-- > > lib/packets.h | 6 +- > > tests/dpif-netdev.at | 4 +- > > 12 files changed, 461 insertions(+), 59 deletions(-) > > > > diff --git a/lib/dp-packet.c b/lib/dp-packet.c index > > ed004c3b9..b5013da9f 100644 > > --- a/lib/dp-packet.c > > +++ b/lib/dp-packet.c > > @@ -543,16 +543,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); > > } > > @@ -562,24 +593,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 > > 70ddf8aa4..80c7ab961 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 | \ @@ > > -138,6 +163,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. > > */ > > @@ -246,6 +275,9 @@ 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 *p, > > + uint64_t flags); > > + > > > > > > /* Frees memory that 'b' points to, as well as 'b' itself. */ @@ > > -478,6 +510,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) { @@ -535,6 > > +583,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) { @@ -554,6 > > +621,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 are no implementation */ } > > + > > +static inline void > > +dp_packet_set_l3_len(struct dp_packet *b OVS_UNUSED, size_t l3_len > > +OVS_UNUSED) { > > + /* There are no implementation */ } > > + > > +static inline void > > +dp_packet_set_l4_len(struct dp_packet *b OVS_UNUSED, size_t l4_len > > +OVS_UNUSED) { > > + /* There are no implementation */ } > > + > > static inline uint32_t * > > dp_packet_ol_flags_ptr(const struct dp_packet *b) { @@ -615,9 > > +700,10 @@ 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'. > > */ > > - b->mbuf.data_len = (uint16_t)v; /* Current seg length. */ > > - b->mbuf.pkt_len = v; /* Total length of all segments > > linked to > > - * this segment. */ > > + /* Current seg length. */ > > + b->mbuf.data_len += (uint16_t)(v - b->mbuf.pkt_len); > > + /* Total length of all segments linked to this segment. */ > > + b->mbuf.pkt_len = v; > > } > > > > static inline uint16_t > > @@ -1030,6 +1116,43 @@ 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 out ipv4. */ static > > +inline bool dp_packet_hwol_is_outer_ipv4(struct dp_packet *b) { > > + return !!(*dp_packet_ol_flags_ptr(b) & > > +DP_PACKET_OL_TX_OUTER_IPV4); } > > + > > +/* Returns 'true' if packet 'b' is marked for out ipv4 csum 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 out udp csum 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) { @@ -1052,6 > > +1175,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 IPv6. */ > > +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) @@ -1105,6 +1236,55 @@ > > 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. It implies that > > + * the packet 'b' is marked 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. It implies that > > + * the packet 'b' is marked 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; } > > + > > /* Returns 'true' if the IP header has good integrity and the > > * checksum in it is complete. */ > > static inline bool > > @@ -1139,9 +1319,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 > > 157694bcf..55f0183c7 100644 > > --- a/lib/dpif-netdev.c > > +++ b/lib/dpif-netdev.c > > @@ -7976,7 +7976,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 fe226cf0f..8f4c38f94 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 > > 55700250d..80d23da5c 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,23 @@ 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 +1375,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 +1395,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); @@ -2445,11 > > +2500,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; > > + } > > > > if (mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) { > > struct tcp_header *th = dp_packet_l4(pkt); @@ -2460,9 > > +2527,16 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct > > rte_mbuf *mbuf) > > return false; > > } > > > > - mbuf->l4_len = TCP_OFFSET(th->tcp_ctl) * 4; > > + 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; > > + } > > + > > mbuf->ol_flags |= RTE_MBUF_F_TX_TCP_CKSUM; > > - mbuf->tso_segsz = dev->mtu - mbuf->l3_len - mbuf->l4_len; > > > > if (mbuf->ol_flags & RTE_MBUF_F_TX_IPV4) { > > mbuf->ol_flags |= RTE_MBUF_F_TX_IP_CKSUM; diff --git > > a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 1a54add87..ae3b9511d > > 100644 > > --- a/lib/netdev-dummy.c > > +++ b/lib/netdev-dummy.c > > @@ -1191,7 +1191,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..505c4efdc 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,14 +240,84 @@ 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(const struct netdev *netdev, > > + 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 (!strcmp(netdev_get_type(netdev), "geneve") || > > + !strcmp(netdev_get_type(netdev), "vxlan")) { > > + > > + if (IP_VER(ip->ip_ihl_ver) == 4) { > > + dp_packet_hwol_set_tx_ipv4(packet); > > + dp_packet_hwol_tx_ip_csum(packet); > > + } 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 (!strcmp(netdev_get_type(netdev), "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 (!strcmp(netdev_get_type(netdev), "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, > > +netdev_tnl_push_udp_header(const struct netdev *netdev, > > struct dp_packet *packet, > > const struct ovs_action_push_tnl *data) { > > struct udp_header *udp; > > int ip_tot_size; > > > > + dp_packet_tnl_ol_process(netdev, packet, data); > > udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len, > > &ip_tot_size, 0); > > > > @@ -241,13 +325,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); > > Hello Dexia, > > I noted on the previous version that there's an issue with removing this > line. Don't we want to set this in all cases? > packet_udp_complete_csum already checks for udp_csum==NULL so we don't have > to worry about that. > > > Cheers, > Mike > > > Hello Mike, > > If packet is geneve or vxlan tunnel, we should set out udp csum here else we > should set udp csum > When udp csum is not zero. And when udp csum is zero, just let it be zero, do > not set any udp csum flag. > Is it right? > > > Best regards, Dexia >
Do the check-system-userspace and check-system-tso tests pass for you with this patch as it is? I'm asking because it breaks two tests for me as well as the automated CI. -M _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
