Hi Tomasz, > > /** > + * Validate general requirements for tx offload in mbuf. > + * > + * This function checks correctness and completeness of Tx offload settings. > + * > + * @param m > + * The packet mbuf to be validated. > + * @return > + * 0 if packet is valid > + */ > +static inline int > +rte_validate_tx_offload(const struct rte_mbuf *m) > +{ > + uint64_t ol_flags = m->ol_flags; > + > + /* Does packet set any of available offloads? */ > + if (!(ol_flags & PKT_TX_OFFLOAD_MASK)) > + return 0; > + > + /* IP checksum can be counted only for IPv4 packet */ > + if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6)) > + return -EINVAL; > + > + /* IP type not set when required */ > + if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG)) > + if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6))) > + return -EINVAL; > + > + /* Check requirements for TSO packet */ > + if (ol_flags & PKT_TX_TCP_SEG) > + if ((m->tso_segsz == 0) || > + ((ol_flags & PKT_TX_IPV4) && > + !(ol_flags & PKT_TX_IP_CKSUM))) > + return -EINVAL; > + > + /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */ > + if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) && > + !(ol_flags & PKT_TX_OUTER_IPV4)) > + return -EINVAL; > + > + return 0; > +} > + > +/** > * Dump an mbuf structure to a file. > * > * Dump all fields for the given packet mbuf and all its associated > diff --git a/lib/librte_net/rte_net.h b/lib/librte_net/rte_net.h > index d4156ae..79669d7 100644 > --- a/lib/librte_net/rte_net.h > +++ b/lib/librte_net/rte_net.h > @@ -38,6 +38,11 @@ > extern "C" { > #endif > > +#include <rte_ip.h> > +#include <rte_udp.h> > +#include <rte_tcp.h> > +#include <rte_sctp.h> > + > /** > * Structure containing header lengths associated to a packet, filled > * by rte_net_get_ptype(). > @@ -86,6 +91,91 @@ struct rte_net_hdr_lens { > uint32_t rte_net_get_ptype(const struct rte_mbuf *m, > struct rte_net_hdr_lens *hdr_lens, uint32_t layers); > > +/** > + * Fix pseudo header checksum > + * > + * This function fixes pseudo header checksum for TSO and non-TSO tcp/udp in > + * provided mbufs packet data. > + * > + * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and > set > + * in packet data, > + * - for TSO the IP payload length is not included in pseudo header. > + * > + * This function expects that used headers are in the first data segment of > + * mbuf, and are not fragmented. > + * > + * @param m > + * The packet mbuf to be validated. > + * @return > + * 0 if checksum is initialized properly > + */ > +static inline int > +rte_phdr_cksum_fix(struct rte_mbuf *m) > +{ > + struct ipv4_hdr *ipv4_hdr; > + struct ipv6_hdr *ipv6_hdr; > + struct tcp_hdr *tcp_hdr; > + struct udp_hdr *udp_hdr; > + uint64_t ol_flags = m->ol_flags; > + uint64_t inner_l3_offset = m->l2_len; > + > + if (ol_flags & PKT_TX_OUTER_IP_CKSUM) > + inner_l3_offset += m->outer_l2_len + m->outer_l3_len; > + > + /* headers are fragmented */ > + if (unlikely(rte_pktmbuf_data_len(m) >= inner_l3_offset + m->l3_len + > + m->l4_len))
Might be better to move that check into rte_validate_tx_offload(), so it would be called only when TX_DEBUG is on. Another thing, shouldn't it be: if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len) ? Konstantin > + return -ENOTSUP; > + > + if ((ol_flags & PKT_TX_UDP_CKSUM) == PKT_TX_UDP_CKSUM) { > + if (ol_flags & PKT_TX_IPV4) { > + ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, > + inner_l3_offset); > + > + if (ol_flags & PKT_TX_IP_CKSUM) > + ipv4_hdr->hdr_checksum = 0; > + > + udp_hdr = (struct udp_hdr *)((char *)ipv4_hdr + > + m->l3_len); > + udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr, > + ol_flags); > + } else { > + ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, > + inner_l3_offset); > + /* non-TSO udp */ > + udp_hdr = rte_pktmbuf_mtod_offset(m, struct udp_hdr *, > + inner_l3_offset + m->l3_len); > + udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr, > + ol_flags); > + } > + } else if ((ol_flags & PKT_TX_TCP_CKSUM) || > + (ol_flags & PKT_TX_TCP_SEG)) { > + if (ol_flags & PKT_TX_IPV4) { > + ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, > + inner_l3_offset); > + > + if (ol_flags & PKT_TX_IP_CKSUM) > + ipv4_hdr->hdr_checksum = 0; > + > + /* non-TSO tcp or TSO */ > + tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + > + m->l3_len); > + tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr, > + ol_flags); > + } else { > + ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, > + inner_l3_offset); > + /* non-TSO tcp or TSO */ > + tcp_hdr = rte_pktmbuf_mtod_offset(m, struct tcp_hdr *, > + inner_l3_offset + m->l3_len); > + tcp_hdr->cksum = rte_ipv6_phdr_cksum(ipv6_hdr, > + ol_flags); > + } > + } > + > + return 0; > +} > + > #ifdef __cplusplus > } > #endif > -- > 1.7.9.5