On 17/12/2025 11:17, Kevin Traynor wrote:
> On 15/12/2025 13:57, David Marchand via dev wrote:
>> Let's consider a TCP packet in a VxLAN tunnel:
>> Ethernet / IP / UDP / VxLAN / Ethernet / IP / TCP / Data
>>
>> The outer UDP checksum is an accumulation of a pseudo header of the
>> outer IP infos (addresses, length, next proto) and the whole packet data:
>> UDP / VxLAN / Ethernet / IP / TCP / Data.
>>
>> Similarly to the outer UDP checksum, the inner TCP checksum is an
>> accumulation of a pseudo header of the inner IP infos and the rest of
>> the packet data.
>>
>> The inner TCP header will contain this inner checksum, so when computing
>> the outer UDP checksum the inner checksum will cancel any participation
>> of the TCP data.
>>
>> As a consequence, the outer UDP checksum depends on the headers content
>> only and can be computed without looking at the data payload.
>>
>> The same principle applies to inner UDP.
>>
>> Thanks to this, we can re-enable IPv4, UDP and TCP inner checksums when
>> outer UDP checksum is not supported.
>>
>> TCP over IPv4 geneve (with checksum on tunnel) on a mlx5 nic:
>> Before:  4.37 Gbits/sec, 100% cpu ("full" csum + SW segmentation)
>> After:   7.80 Gbits/sec, 100% cpu (constant csum + SW segmentation)
>>
>> Reported-at: https://issues.redhat.com/browse/FDP-1897
>> Signed-off-by: David Marchand <[email protected]>
>> ---
> 
> Just a couple of minor comments on the rework. They could be done during
> apply if they are the only comments.
> 
>> Changes since v2:
>> - added coverage for IPv4 traffic in IPv6 tunnel,
>> - removed asserts,
>> - optimised the case of null inner UDP checksum,
>>
>> Changes since v1:
>> - fixed outer UDP checksum for inner UDP traffic with no checksum,
>> - fixed inner L4 bad or unknown checksums handling,
>> - dropped computing and setting inner IP checksum (for partial status),
>>   instead inner IPv4 header content is simply skipped for good and
>>   partial status,
>> - fixed inner IP bad or unknown checksums handling (we can still
>>   apply the optimisation),
>> - added unit tests,
>>
>> ---
>>  lib/dp-packet-gso.c  |  10 ++--
>>  lib/dp-packet.c      |  21 +++++----
>>  lib/dp-packet.h      |  24 ++++++++++
>>  lib/netdev-dpdk.c    |  84 ++++++++++++++--------------------
>>  lib/packets.c        | 106 +++++++++++++++++++++++++++++++++++++++++++
>>  lib/packets.h        |   1 +
>>  tests/dpif-netdev.at |  76 +++++++++++++++++++++++--------
>>  7 files changed, 239 insertions(+), 83 deletions(-)
>>
>> diff --git a/lib/dp-packet-gso.c b/lib/dp-packet-gso.c
>> index 362bc8f66d..fe7186ddf4 100644
>> --- a/lib/dp-packet-gso.c
>> +++ b/lib/dp-packet-gso.c
>> @@ -66,17 +66,15 @@ int
>>  dp_packet_gso_nr_segs(struct dp_packet *p)
>>  {
>>      uint16_t segsz = dp_packet_get_tso_segsz(p);
>> -    const char *data_tail;
>> -    const char *data_pos;
>> +    uint32_t data_length;
>>  
>>      if (dp_packet_tunnel(p)) {
>> -        data_pos = dp_packet_get_inner_tcp_payload(p);
>> +        data_length = dp_packet_get_inner_tcp_payload_length(p);
>>      } else {
>> -        data_pos = dp_packet_get_tcp_payload(p);
>> +        data_length = dp_packet_get_tcp_payload_length(p);
>>      }
>> -    data_tail = (char *) dp_packet_tail(p) - dp_packet_l2_pad_size(p);
>>  
>> -    return DIV_ROUND_UP(data_tail - data_pos, segsz);
>> +    return DIV_ROUND_UP(data_length, segsz);
>>  }
>>  
>>  /* Perform software segmentation on packet 'p'.
>> diff --git a/lib/dp-packet.c b/lib/dp-packet.c
>> index b893fbd396..9bcf14c272 100644
>> --- a/lib/dp-packet.c
>> +++ b/lib/dp-packet.c
>> @@ -593,19 +593,22 @@ dp_packet_ol_send_prepare(struct dp_packet *p, 
>> uint64_t flags)
>>          return;
>>      }
>>  
>> -    if (dp_packet_tunnel_geneve(p)
>> -        || dp_packet_tunnel_vxlan(p)) {
>> -
>> +    if (dp_packet_tunnel_geneve(p) || dp_packet_tunnel_vxlan(p)) {
>>          /* If the TX interface doesn't support UDP tunnel offload but does
>> -         * support inner checksum offload and an outer UDP checksum is
>> -         * required, then we can't offload inner checksum either. As that 
>> would
>> +         * support inner SCTP checksum offload and an outer UDP checksum is
>> +         * required, then we can't offload inner checksum either as that 
>> would
>>           * invalidate the outer checksum. */
>>          if (!(flags & NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
>>              && dp_packet_l4_checksum_partial(p)) {
>> -            flags &= ~(NETDEV_TX_OFFLOAD_TCP_CKSUM |
>> -                       NETDEV_TX_OFFLOAD_UDP_CKSUM |
>> -                       NETDEV_TX_OFFLOAD_SCTP_CKSUM |
>> -                       NETDEV_TX_OFFLOAD_IPV4_CKSUM);
>> +            flags &= ~NETDEV_TX_OFFLOAD_SCTP_CKSUM;
>> +            if (!packet_udp_tunnel_csum(p)) {
>> +                /* Similarly to the previous comment, since the outer UDP
>> +                 * checksum optimisation did not happen, invalidate inner
>> +                 * checksum offloads support. */
>> +                flags &= ~(NETDEV_TX_OFFLOAD_TCP_CKSUM |
>> +                           NETDEV_TX_OFFLOAD_UDP_CKSUM |
>> +                           NETDEV_TX_OFFLOAD_IPV4_CKSUM);
>> +            }
>>          }
>>      }
>>  
>> diff --git a/lib/dp-packet.h b/lib/dp-packet.h
>> index 285d0e43f6..6a4a61922b 100644
>> --- a/lib/dp-packet.h
>> +++ b/lib/dp-packet.h
>> @@ -585,6 +585,18 @@ dp_packet_get_tcp_payload_length(const struct dp_packet 
>> *pkt)
>>      }
>>  }
>>  
>> +static inline uint32_t
>> +dp_packet_get_inner_tcp_payload_length(const struct dp_packet *pkt)
>> +{
>> +    const char *tcp_payload = dp_packet_get_inner_tcp_payload(pkt);
>> +    if (tcp_payload) {
>> +        return ((char *) dp_packet_tail(pkt) - dp_packet_l2_pad_size(pkt)
>> +                - tcp_payload);
>> +    } else {
>> +        return 0;
>> +    }
>> +}
>> +
>>  static inline const void *
>>  dp_packet_get_udp_payload(const struct dp_packet *b)
>>  {
>> @@ -1171,6 +1183,12 @@ dp_packet_inner_ip_checksum_set_partial(struct 
>> dp_packet *p)
>>      p->offloads |= DP_PACKET_OL_INNER_IP_CKSUM_MASK;
>>  }
>>  
>> +static inline bool OVS_WARN_UNUSED_RESULT
>> +dp_packet_inner_ip_checksum_valid(const struct dp_packet *p)
>> +{
>> +    return !!(p->offloads & DP_PACKET_OL_INNER_IP_CKSUM_GOOD);
>> +}
>> +
>>  /* Calculate and set the IPv4 header checksum in packet 'p'. */
>>  static inline void
>>  dp_packet_ip_set_header_csum(struct dp_packet *p, bool inner)
>> @@ -1364,6 +1382,12 @@ dp_packet_inner_l4_checksum_set_partial(struct 
>> dp_packet *p)
>>      p->offloads |= DP_PACKET_OL_INNER_L4_CKSUM_MASK;
>>  }
>>  
>> +static inline bool OVS_WARN_UNUSED_RESULT
>> +dp_packet_inner_l4_checksum_valid(const struct dp_packet *p)
>> +{
>> +    return !!(p->offloads & DP_PACKET_OL_INNER_L4_CKSUM_GOOD);
>> +}
>> +
>>  static inline void
>>  dp_packet_reset_packet(struct dp_packet *b, int off)
>>  {
>> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
>> index 29b1b21d64..38cf0ebb2e 100644
>> --- a/lib/netdev-dpdk.c
>> +++ b/lib/netdev-dpdk.c
>> @@ -2648,59 +2648,43 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk 
>> *dev, struct rte_mbuf *mbuf)
>>      }
>>  
>>      if (dp_packet_tunnel(pkt)) {
>> -        if (dp_packet_ip_checksum_partial(pkt)
>> -            || dp_packet_l4_checksum_partial(pkt)) {
>> -            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);
>> -
>> -            if (dp_packet_tunnel_geneve(pkt)) {
>> -                mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_GENEVE;
>> -            } else if (dp_packet_tunnel_vxlan(pkt)) {
>> -                mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_VXLAN;
>> -            } else {
>> -                ovs_assert(dp_packet_tunnel_gre(pkt));
>> -                mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_GRE;
>> -            }
>> -
>> -            if (dp_packet_ip_checksum_partial(pkt)) {
>> -                mbuf->ol_flags |= RTE_MBUF_F_TX_OUTER_IP_CKSUM;
>> -            }
>> +        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);
>> +
>> +        if (dp_packet_tunnel_geneve(pkt)) {
>> +            mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_GENEVE;
>> +        } else if (dp_packet_tunnel_vxlan(pkt)) {
>> +            mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_VXLAN;
>> +        } else {
>> +            ovs_assert(dp_packet_tunnel_gre(pkt));
>> +            mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_GRE;
>> +        }
>>  
>> -            if (dp_packet_l4_checksum_partial(pkt)) {
>> -                ovs_assert(dp_packet_l4_proto_udp(pkt));
>> -                mbuf->ol_flags |= RTE_MBUF_F_TX_OUTER_UDP_CKSUM;
>> -            }
>> +        if (dp_packet_ip_checksum_partial(pkt)) {
>> +            mbuf->ol_flags |= RTE_MBUF_F_TX_OUTER_IP_CKSUM;
>> +        }
>>  
>> -            ip = dp_packet_l3(pkt);
>> -            mbuf->ol_flags |= IP_VER(ip->ip_ihl_ver) == 4
>> -                              ? RTE_MBUF_F_TX_OUTER_IPV4
>> -                              : RTE_MBUF_F_TX_OUTER_IPV6;
>> -
>> -            /* Inner L2 length must account for the tunnel header length. */
>> -            l2 = dp_packet_l4(pkt);
>> -            l3 = dp_packet_inner_l3(pkt);
>> -            l3_csum = dp_packet_inner_ip_checksum_partial(pkt);
>> -            l4 = dp_packet_inner_l4(pkt);
>> -            l4_csum = dp_packet_inner_l4_checksum_partial(pkt);
>> -            is_tcp = dp_packet_inner_l4_proto_tcp(pkt);
>> -            is_udp = dp_packet_inner_l4_proto_udp(pkt);
>> -            is_sctp = dp_packet_inner_l4_proto_sctp(pkt);
>> -        } else {
>> -            mbuf->outer_l2_len = 0;
>> -            mbuf->outer_l3_len = 0;
>> -
>> -            /* Skip outer headers. */
>> -            l2 = dp_packet_eth(pkt);
>> -            l3 = dp_packet_inner_l3(pkt);
>> -            l3_csum = dp_packet_inner_ip_checksum_partial(pkt);
>> -            l4 = dp_packet_inner_l4(pkt);
>> -            l4_csum = dp_packet_inner_l4_checksum_partial(pkt);
>> -            is_tcp = dp_packet_inner_l4_proto_tcp(pkt);
>> -            is_udp = dp_packet_inner_l4_proto_udp(pkt);
>> -            is_sctp = dp_packet_inner_l4_proto_sctp(pkt);
>> +        if (dp_packet_l4_checksum_partial(pkt)) {
>> +            ovs_assert(dp_packet_l4_proto_udp(pkt));
>> +            mbuf->ol_flags |= RTE_MBUF_F_TX_OUTER_UDP_CKSUM;
>>          }
>> +
>> +        ip = dp_packet_l3(pkt);
>> +        mbuf->ol_flags |= IP_VER(ip->ip_ihl_ver) == 4
>> +                          ? RTE_MBUF_F_TX_OUTER_IPV4
>> +                          : RTE_MBUF_F_TX_OUTER_IPV6;
>> +
>> +        /* Inner L2 length must account for the tunnel header length. */
>> +        l2 = dp_packet_l4(pkt);
>> +        l3 = dp_packet_inner_l3(pkt);
>> +        l3_csum = dp_packet_inner_ip_checksum_partial(pkt);
>> +        l4 = dp_packet_inner_l4(pkt);
>> +        l4_csum = dp_packet_inner_l4_checksum_partial(pkt);
>> +        is_tcp = dp_packet_inner_l4_proto_tcp(pkt);
>> +        is_udp = dp_packet_inner_l4_proto_udp(pkt);
>> +        is_sctp = dp_packet_inner_l4_proto_sctp(pkt);
>>      } else {
>>          mbuf->outer_l2_len = 0;
>>          mbuf->outer_l3_len = 0;
>> diff --git a/lib/packets.c b/lib/packets.c
>> index a0bb2ad482..3d12563e3b 100644
>> --- a/lib/packets.c
>> +++ b/lib/packets.c
>> @@ -2085,6 +2085,112 @@ out:
>>      }
>>  }
>>  
>> +/* This helper computes a "constant" UDP checksum without looking at the
>> + * L4 payload.
>> + *
>> + * This is possible when L4 is either TCP or UDP: the L4 payload checksum
>> + * is either computed in SW or in HW later, but its contribution to the
>> + * outer checksum is cancelled by the L4 payload being part of the global
>> + * packet sum. */
>> +bool
>> +packet_udp_tunnel_csum(struct dp_packet *p)
>> +{
>> +    const ovs_be16 *inner_l4_csum_p;
>> +    struct ip_header *inner_ip;
>> +    const void *inner_l4_data;
>> +    struct udp_header *udp;
>> +    ovs_be16 inner_l4_csum;
>> +    uint32_t partial_csum;
>> +    struct ip_header *ip;
>> +    uint32_t inner_csum;
>> +    bool inner_ipv4;
>> +    void *inner_l4;
>> +
>> +    inner_ip = dp_packet_inner_l3(p);
>> +    inner_l4 = dp_packet_inner_l4(p);
>> +    ip = dp_packet_l3(p);
>> +    udp = dp_packet_l4(p);
>> +
>> +    if (dp_packet_inner_l4_proto_tcp(p)) {
>> +        inner_l4_csum_p = &(((struct tcp_header *) inner_l4)->tcp_csum);
>> +        inner_l4_data = dp_packet_get_inner_tcp_payload(p);
>> +        if (!inner_l4_data) {
>> +            /* Malformed packet. */
>> +            return false;
>> +        }
>> +    } else if (dp_packet_inner_l4_proto_udp(p)) {
>> +        inner_l4_csum_p = &(((struct udp_header *) inner_l4)->udp_csum);
>> +        inner_l4_data = (char *) inner_l4 + sizeof (struct udp_header);
>> +        if (*inner_l4_csum_p == 0) {
>> +            /* There is no nested checksum.
>> +             * No choice but compute a full checksum. */
>> +            return false;
>> +        }
>> +    } else {
>> +            /* This optimisation applies only to inner TCP/UDP. */
>> +            return false;
> 
> indent is off here
> 
>> +    }
>> +
>> +    if (!dp_packet_inner_l4_checksum_valid(p)) {
>> +        /* We have no idea about the contribution of the payload data
>> +         * and what the L4 checksum put in the packet data looks like.
>> +         * Simpler is to let a full checksum happen. */
>> +        return false;
>> +    }
>> +> +    inner_ipv4 = IP_VER(inner_ip->ip_ihl_ver) == 4;
>> +    if (inner_ipv4) {
>> +        inner_csum = packet_csum_pseudoheader(inner_ip);
>> +    } else {
>> +        struct ovs_16aligned_ip6_hdr *inner_ip6 = dp_packet_inner_l3(p);
>> +
>> +        inner_csum = packet_csum_pseudoheader6(inner_ip6);
>> +    }
>> +
>> +    inner_csum = csum_continue(inner_csum, inner_l4,
>> +        (char *) inner_l4_csum_p - (char *) inner_l4);
>> +    inner_l4_csum = csum_finish(csum_continue(inner_csum, inner_l4_csum_p + 
>> 1,
>> +        (char *) inner_l4_data - (char *)(inner_l4_csum_p + 1)));
>> +    /* Important: for inner UDP, a null inner_l4_csum here should in theory 
>> be
>> +     * replaced with 0xffff. However, since the only use of inner_l4_csum is
>> +     * for the final outer checksum with a csum_add16() below, we can skip 
>> this
>> +     * entirely because adding 0xffff after reducing as the same impact than
>> +     * adding 0. */
> 
> Last sentence needs a small reword and we can add a reference to where
> the reduction is done. e.g.
> "However, since the only use of inner_l4_csum is for the final outer
> checksum with a csum_add16() below, we can skip this entirely because
> adding 0xffff will have the same effect as adding 0x0 after reducing in
> csum_finish."
> 
> wdyt?
> 

I meant to add, with these minor non-functional fixes LGTM

Acked-by: Kevin Traynor <[email protected]>

>> +
>> +    udp->udp_csum = 0;
>> +    if (IP_VER(ip->ip_ihl_ver) == 4) {
>> +        partial_csum = packet_csum_pseudoheader(ip);
>> +    } else {
>> +        struct ovs_16aligned_ip6_hdr *ip6 = dp_packet_l3(p);
>> +
>> +        partial_csum = packet_csum_pseudoheader6(ip6);
>> +    }
>> +
>> +    partial_csum = csum_continue(partial_csum, udp,
>> +        (char *) inner_ip - (char *) udp);
>> +    if (!inner_ipv4 || !dp_packet_inner_ip_checksum_valid(p)) {
>> +        /* IPv6 has no checksum, so for inner IPv6, we need to sum the 
>> header.
>> +         *
>> +         * In IPv4 case, if inner checksum is already good or HW offload
>> +         * has been requested, the (final) sum of the IPv4 header will be 0.
>> +         * Otherwise, we need to sum the header like for IPv6. */
>> +        partial_csum = csum_continue(partial_csum, inner_ip,
>> +            (char *) inner_l4 - (char *) inner_ip);
>> +    }
>> +    partial_csum = csum_continue(partial_csum, inner_l4,
>> +        (char *) inner_l4_csum_p - (char *) inner_l4);
>> +    partial_csum = csum_add16(partial_csum, inner_l4_csum);
>> +    partial_csum = csum_continue(partial_csum, inner_l4_csum_p + 1,
>> +        (char *) inner_l4_data - (char *)(inner_l4_csum_p + 1));
>> +    udp->udp_csum = csum_finish(partial_csum);
>> +    if (!udp->udp_csum) {
>> +        udp->udp_csum = htons(0xffff);
>> +    }
>> +    dp_packet_l4_checksum_set_good(p);
>> +
>> +    return true;
>> +}
>> +
>>  /* Set SCTP checksum field in packet 'p' with complete checksum.
>>   * The packet must have the L3 and L4 offsets. */
>>  void
>> diff --git a/lib/packets.h b/lib/packets.h
>> index 6eba07700a..843e9653a8 100644
>> --- a/lib/packets.h
>> +++ b/lib/packets.h
>> @@ -1689,6 +1689,7 @@ bool packet_rh_present(struct dp_packet *packet, 
>> uint8_t *nexthdr,
>>  void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);
>>  void packet_tcp_complete_csum(struct dp_packet *, bool is_inner);
>>  void packet_udp_complete_csum(struct dp_packet *, bool is_inner);
>> +bool packet_udp_tunnel_csum(struct dp_packet *);
>>  void packet_sctp_complete_csum(struct dp_packet *, bool is_inner);
>>  
>>  #define DNS_HEADER_LEN 12
>> diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
>> index 1125a0364f..c41c1e18d3 100644
>> --- a/tests/dpif-netdev.at
>> +++ b/tests/dpif-netdev.at
>> @@ -1371,14 +1371,34 @@ AT_CHECK([ovs-vsctl set Interface p2 
>> options:ol_ip_tx_csum_disabled=true])
>>  cat good_csum_expected | sed -e "s/339e/0000/" > half_bad_csum_expected
>>  CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [half_bad_csum_expected])
>>  
>> +dnl Special case 2, to check if Tx offloads did happen in the driver
>> +dnl with the outer UDP optimisation.
>> +dnl A valid inner L4 checksum is required for the optimisation to trigger.
>> +AT_CHECK([ovs-vsctl set Interface p1 options:ol_l4_rx_csum_set_good=true])
>> +
>> +cat good_csum_expected | sed -e "s/339e/0000/" -e "s/bd3c/423c/" > 
>> half_bad_csum_expected
>> +CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [half_bad_csum_expected])
>> +
>> +AT_CHECK([ovs-vsctl remove Interface p1 options ol_l4_rx_csum_set_good])
>> +
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_ip_tx_csum_disabled])
>>  
>> -dnl Special case 2, to check if inner Tx offload did happen in the driver.
>> +dnl Special case 3, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_ip_tx_csum])
>>  
>>  dnl The inner part will be fixed by datapath.
>>  CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>>  
>> +dnl Special case 4, to check if Tx offloads did happen in the driver
>> +dnl with the outer UDP optimisation.
>> +dnl A valid inner L4 checksum is required for the optimisation to trigger.
>> +AT_CHECK([ovs-vsctl set Interface p1 options:ol_l4_rx_csum_set_good=true])
>> +
>> +cat good_csum_expected | sed -e "s/bd3c/423c/" > half_bad_csum_expected
>> +CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [half_bad_csum_expected])
>> +
>> +AT_CHECK([ovs-vsctl remove Interface p1 options ol_l4_rx_csum_set_good])
>> +
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_ip_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_ip_tx_csum])
>>  
>> @@ -1511,8 +1531,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/7715/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -1683,8 +1703,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/c6de/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -1818,8 +1838,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/f165/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -1990,8 +2010,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/412f/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -2218,14 +2238,34 @@ AT_CHECK([ovs-vsctl set Interface p2 
>> options:ol_ip_tx_csum_disabled=true])
>>  cat good_csum_expected | sed -e "s/339e/0000/" > half_bad_csum_expected
>>  CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [half_bad_csum_expected])
>>  
>> +dnl Special case 2, to check if Tx offloads did happen in the driver
>> +dnl with the outer UDP optimisation.
>> +dnl A valid inner L4 checksum is required for the optimisation to trigger.
>> +AT_CHECK([ovs-vsctl set Interface p1 options:ol_l4_rx_csum_set_good=true])
>> +
>> +cat good_csum_expected | sed -e "s/339e/0000/" -e "s/bd3c/423c/" > 
>> half_bad_csum_expected
>> +CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [half_bad_csum_expected])
>> +
>> +AT_CHECK([ovs-vsctl remove Interface p1 options ol_l4_rx_csum_set_good])
>> +
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_ip_tx_csum_disabled])
>>  
>> -dnl Special case 2, to check if inner Tx offload did happen in the driver.
>> +dnl Special case 3, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_ip_tx_csum])
>>  
>>  dnl The inner part will be fixed by datapath.
>>  CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>>  
>> +dnl Special case 4, to check if Tx offloads did happen in the driver
>> +dnl with the outer UDP optimisation.
>> +dnl A valid inner L4 checksum is required for the optimisation to trigger.
>> +AT_CHECK([ovs-vsctl set Interface p1 options:ol_l4_rx_csum_set_good=true])
>> +
>> +cat good_csum_expected | sed -e "s/bd3c/423c/" > half_bad_csum_expected
>> +CHECK_FWD_PACKET(p1, p2, ol_ip_rx_csum_set_good, [bad_frame], 
>> [half_bad_csum_expected])
>> +
>> +AT_CHECK([ovs-vsctl remove Interface p1 options ol_l4_rx_csum_set_good])
>> +
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_ip_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_ip_tx_csum])
>>  
>> @@ -2358,8 +2398,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/7715/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -2530,8 +2570,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/c6de/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -2665,8 +2705,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/f165/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
>> @@ -2837,8 +2877,8 @@ AT_CHECK([ovs-vsctl remove Interface p2 options 
>> ol_out_udp_tx_csum_disabled])
>>  dnl Special case 2, to check if inner Tx offload did happen in the driver.
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_out_udp_tx_csum])
>>  
>> -dnl The inner part will be fixed by datapath.
>> -CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [good_csum_expected])
>> +cat good_csum_expected | sed -e "s/412f/dead/" > bad_csum_updated
>> +CHECK_FWD_PACKET(p1, p2, ol_l4_rx_csum_set_good, [bad_frame], 
>> [bad_csum_updated])
>>  
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum_disabled])
>>  AT_CHECK([ovs-vsctl remove Interface p2 options ol_l4_tx_csum])
> 

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to