diff --git a/lib/dp-packet.c b/lib/dp-packet.c index cd2623500e3..72f6d09ac7f 100644 --- a/lib/dp-packet.c +++ b/lib/dp-packet.c @@ -192,10 +192,8 @@ dp_packet_clone_with_headroom(const struct dp_packet *buffer, size_t headroom) sizeof(struct dp_packet) - offsetof(struct dp_packet, l2_pad_size)); -#ifdef DPDK_NETDEV - new_buffer->mbuf.ol_flags = buffer->mbuf.ol_flags; - new_buffer->mbuf.ol_flags &= ~DPDK_MBUF_NON_OFFLOADING_FLAGS; -#endif + *dp_packet_ol_flags_ptr(new_buffer) = *dp_packet_ol_flags_ptr(buffer); + *dp_packet_ol_flags_ptr(new_buffer) &= DP_PACKET_OL_SUPPORTED_MASK; if (dp_packet_rss_valid(buffer)) { dp_packet_set_rss_hash(new_buffer, dp_packet_get_rss_hash(buffer)); diff --git a/lib/dp-packet.h b/lib/dp-packet.h index 9f8991faad5..0430cca8ebb 100644 --- a/lib/dp-packet.h +++ b/lib/dp-packet.h @@ -48,18 +48,62 @@ enum OVS_PACKED_ENUM dp_packet_source { #define DP_PACKET_CONTEXT_SIZE 64 -#ifndef DPDK_NETDEV +#ifdef DPDK_NETDEV +#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = DPDK_DEF +#else +#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = GENERIC_DEF +#endif + /* Bit masks for the 'ol_flags' member of the 'dp_packet' structure. */ enum dp_packet_offload_mask { - DP_PACKET_OL_RSS_HASH_MASK = 0x1, /* Is the 'rss_hash' valid? */ - DP_PACKET_OL_FLOW_MARK_MASK = 0x2, /* Is the 'flow_mark' valid? */ + /* Value 0 is not used. */ + /* Is the 'rss_hash' valid? */ + DEF_OL_FLAG(DP_PACKET_OL_RSS_HASH, PKT_RX_RSS_HASH, 0x1), + /* Is the 'flow_mark' valid? */ + DEF_OL_FLAG(DP_PACKET_OL_FLOW_MARK, PKT_RX_FDIR_ID, 0x2), + /* Bad L4 checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_BAD, PKT_RX_L4_CKSUM_BAD, 0x4), + /* Bad IP checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_BAD, PKT_RX_IP_CKSUM_BAD, 0x8), + /* Valid L4 checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_GOOD, PKT_RX_L4_CKSUM_GOOD, 0x10), + /* Valid IP checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_GOOD, PKT_RX_IP_CKSUM_GOOD, 0x20), + /* TCP Segmentation Offload. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_SEG, PKT_TX_TCP_SEG, 0x40), + /* Offloaded packet is IPv4. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_IPV4, PKT_TX_IPV4, 0x80), + /* Offloaded packet is IPv6. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_IPV6, PKT_TX_IPV6, 0x100), + /* Offload TCP checksum. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_CKSUM, PKT_TX_TCP_CKSUM, 0x200), + /* Offload UDP checksum. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_UDP_CKSUM, PKT_TX_UDP_CKSUM, 0x400), + /* Offload SCTP checksum. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_SCTP_CKSUM, PKT_TX_SCTP_CKSUM, 0x800), + /* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */ }; -#else -/* DPDK mbuf ol_flags that are not really an offload flags. These are mostly - * related to mbuf memory layout and OVS should not touch/clear them. */ -#define DPDK_MBUF_NON_OFFLOADING_FLAGS (EXT_ATTACHED_MBUF | \ - IND_ATTACHED_MBUF) -#endif + +#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) + +#define DP_PACKET_OL_TX_L4_MASK (DP_PACKET_OL_TX_TCP_CKSUM | \ + DP_PACKET_OL_TX_UDP_CKSUM | \ + DP_PACKET_OL_TX_SCTP_CKSUM) +#define DP_PACKET_OL_RX_IP_CKSUM_MASK (DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ + DP_PACKET_OL_RX_IP_CKSUM_BAD) +#define DP_PACKET_OL_RX_L4_CKSUM_MASK (DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ + DP_PACKET_OL_RX_L4_CKSUM_BAD) /* Buffer for holding packet data. A dp_packet is automatically reallocated * as necessary if it grows too large for the available memory. @@ -450,6 +494,45 @@ dp_packet_get_nd_payload(const struct dp_packet *b) ? (const char *)dp_packet_l4(b) + ND_MSG_LEN : NULL; } +#ifdef DPDK_NETDEV +static inline uint64_t * +dp_packet_ol_flags_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint64_t *, &b->mbuf.ol_flags); +} + +static inline uint32_t * +dp_packet_rss_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->mbuf.hash.rss); +} + +static inline uint32_t * +dp_packet_flow_mark_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->mbuf.hash.fdir.hi); +} + +#else +static inline uint32_t * +dp_packet_ol_flags_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->ol_flags); +} + +static inline uint32_t * +dp_packet_rss_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->rss_hash); +} + +static inline uint32_t * +dp_packet_flow_mark_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->flow_mark); +} +#endif + #ifdef DPDK_NETDEV BUILD_ASSERT_DECL(offsetof(struct dp_packet, mbuf) == 0); @@ -521,168 +604,6 @@ dp_packet_set_allocated(struct dp_packet *b, uint16_t s) b->mbuf.buf_len = s; } -/* Returns 'true' if packet 'b' is marked for TCP segmentation offloading. */ -static inline bool -dp_packet_hwol_is_tso(const struct dp_packet *b) -{ - return !!(b->mbuf.ol_flags & PKT_TX_TCP_SEG); -} - -/* Returns 'true' if packet 'b' is marked for IPv4 checksum offloading. */ -static inline bool -dp_packet_hwol_is_ipv4(const struct dp_packet *b) -{ - return !!(b->mbuf.ol_flags & PKT_TX_IPV4); -} - -/* Returns the L4 cksum offload bitmask. */ -static inline uint64_t -dp_packet_hwol_l4_mask(const struct dp_packet *b) -{ - return b->mbuf.ol_flags & PKT_TX_L4_MASK; -} - -/* Returns 'true' if packet 'b' is marked for TCP checksum offloading. */ -static inline bool -dp_packet_hwol_l4_is_tcp(const struct dp_packet *b) -{ - return (b->mbuf.ol_flags & PKT_TX_L4_MASK) == PKT_TX_TCP_CKSUM; -} - -/* Returns 'true' if packet 'b' is marked for UDP checksum offloading. */ -static inline bool -dp_packet_hwol_l4_is_udp(struct dp_packet *b) -{ - return (b->mbuf.ol_flags & PKT_TX_L4_MASK) == PKT_TX_UDP_CKSUM; -} - -/* Returns 'true' if packet 'b' is marked for SCTP checksum offloading. */ -static inline bool -dp_packet_hwol_l4_is_sctp(struct dp_packet *b) -{ - return (b->mbuf.ol_flags & PKT_TX_L4_MASK) == PKT_TX_SCTP_CKSUM; -} - -/* Mark packet 'b' for IPv4 checksum offloading. */ -static inline void -dp_packet_hwol_set_tx_ipv4(struct dp_packet *b) -{ - b->mbuf.ol_flags |= PKT_TX_IPV4; -} - -/* Mark packet 'b' for IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_tx_ipv6(struct dp_packet *b) -{ - b->mbuf.ol_flags |= PKT_TX_IPV6; -} - -/* Mark packet 'b' for TCP checksum offloading. It implies that either - * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_csum_tcp(struct dp_packet *b) -{ - b->mbuf.ol_flags |= PKT_TX_TCP_CKSUM; -} - -/* Mark packet 'b' for UDP checksum offloading. It implies that either - * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_csum_udp(struct dp_packet *b) -{ - b->mbuf.ol_flags |= PKT_TX_UDP_CKSUM; -} - -/* Mark packet 'b' for SCTP checksum offloading. It implies that either - * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_csum_sctp(struct dp_packet *b) -{ - b->mbuf.ol_flags |= PKT_TX_SCTP_CKSUM; -} - -/* Mark packet 'b' for TCP segmentation offloading. It implies that - * either the packet 'b' is marked for IPv4 or IPv6 checksum offloading - * and also for TCP checksum offloading. */ -static inline void -dp_packet_hwol_set_tcp_seg(struct dp_packet *b) -{ - b->mbuf.ol_flags |= PKT_TX_TCP_SEG; -} - -/* Returns the RSS hash of the packet 'p'. Note that the returned value is - * correct only if 'dp_packet_rss_valid(p)' returns true */ -static inline uint32_t -dp_packet_get_rss_hash(const struct dp_packet *p) -{ - return p->mbuf.hash.rss; -} - -static inline void -dp_packet_set_rss_hash(struct dp_packet *p, uint32_t hash) -{ - p->mbuf.hash.rss = hash; - p->mbuf.ol_flags |= PKT_RX_RSS_HASH; -} - -static inline bool -dp_packet_rss_valid(const struct dp_packet *p) -{ - return p->mbuf.ol_flags & PKT_RX_RSS_HASH; -} - -static inline void -dp_packet_reset_offload(struct dp_packet *p) -{ - p->mbuf.ol_flags &= DPDK_MBUF_NON_OFFLOADING_FLAGS; -} - -static inline bool -dp_packet_ip_checksum_valid(const struct dp_packet *p) -{ - return (p->mbuf.ol_flags & PKT_RX_IP_CKSUM_MASK) == - PKT_RX_IP_CKSUM_GOOD; -} - -static inline bool -dp_packet_ip_checksum_bad(const struct dp_packet *p) -{ - return (p->mbuf.ol_flags & PKT_RX_IP_CKSUM_MASK) == - PKT_RX_IP_CKSUM_BAD; -} - -static inline bool -dp_packet_l4_checksum_valid(const struct dp_packet *p) -{ - return (p->mbuf.ol_flags & PKT_RX_L4_CKSUM_MASK) == - PKT_RX_L4_CKSUM_GOOD; -} - -static inline bool -dp_packet_l4_checksum_bad(const struct dp_packet *p) -{ - return (p->mbuf.ol_flags & PKT_RX_L4_CKSUM_MASK) == - PKT_RX_L4_CKSUM_BAD; -} - -static inline bool -dp_packet_has_flow_mark(const struct dp_packet *p, uint32_t *mark) -{ - if (p->mbuf.ol_flags & PKT_RX_FDIR_ID) { - *mark = p->mbuf.hash.fdir.hi; - return true; - } - - return false; -} - -static inline void -dp_packet_set_flow_mark(struct dp_packet *p, uint32_t mark) -{ - p->mbuf.hash.fdir.hi = mark; - p->mbuf.ol_flags |= PKT_RX_FDIR_ID; -} - #else /* DPDK_NETDEV */ static inline void @@ -739,151 +660,6 @@ dp_packet_set_allocated(struct dp_packet *b, uint16_t s) b->allocated_ = s; } -/* There are no implementation when not DPDK enabled datapath. */ -static inline bool -dp_packet_hwol_is_tso(const struct dp_packet *b OVS_UNUSED) -{ - return false; -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline bool -dp_packet_hwol_is_ipv4(const struct dp_packet *b OVS_UNUSED) -{ - return false; -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline uint64_t -dp_packet_hwol_l4_mask(const struct dp_packet *b OVS_UNUSED) -{ - return 0; -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline bool -dp_packet_hwol_l4_is_tcp(const struct dp_packet *b OVS_UNUSED) -{ - return false; -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline bool -dp_packet_hwol_l4_is_udp(const struct dp_packet *b OVS_UNUSED) -{ - return false; -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline bool -dp_packet_hwol_l4_is_sctp(const struct dp_packet *b OVS_UNUSED) -{ - return false; -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline void -dp_packet_hwol_set_tx_ipv4(struct dp_packet *b OVS_UNUSED) -{ -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline void -dp_packet_hwol_set_tx_ipv6(struct dp_packet *b OVS_UNUSED) -{ -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline void -dp_packet_hwol_set_csum_tcp(struct dp_packet *b OVS_UNUSED) -{ -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline void -dp_packet_hwol_set_csum_udp(struct dp_packet *b OVS_UNUSED) -{ -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline void -dp_packet_hwol_set_csum_sctp(struct dp_packet *b OVS_UNUSED) -{ -} - -/* There are no implementation when not DPDK enabled datapath. */ -static inline void -dp_packet_hwol_set_tcp_seg(struct dp_packet *b OVS_UNUSED) -{ -} - -/* Returns the RSS hash of the packet 'p'. Note that the returned value is - * correct only if 'dp_packet_rss_valid(p)' returns true */ -static inline uint32_t -dp_packet_get_rss_hash(const struct dp_packet *p) -{ - return p->rss_hash; -} - -static inline void -dp_packet_set_rss_hash(struct dp_packet *p, uint32_t hash) -{ - p->rss_hash = hash; - p->ol_flags |= DP_PACKET_OL_RSS_HASH_MASK; -} - -static inline bool -dp_packet_rss_valid(const struct dp_packet *p) -{ - return p->ol_flags & DP_PACKET_OL_RSS_HASH_MASK; -} - -static inline void -dp_packet_reset_offload(struct dp_packet *p) -{ - p->ol_flags = 0; -} - -static inline bool -dp_packet_ip_checksum_valid(const struct dp_packet *p OVS_UNUSED) -{ - return false; -} - -static inline bool -dp_packet_ip_checksum_bad(const struct dp_packet *p OVS_UNUSED) -{ - return false; -} - -static inline bool -dp_packet_l4_checksum_valid(const struct dp_packet *p OVS_UNUSED) -{ - return false; -} - -static inline bool -dp_packet_l4_checksum_bad(const struct dp_packet *p OVS_UNUSED) -{ - return false; -} - -static inline bool -dp_packet_has_flow_mark(const struct dp_packet *p, uint32_t *mark) -{ - if (p->ol_flags & DP_PACKET_OL_FLOW_MARK_MASK) { - *mark = p->flow_mark; - return true; - } - return false; -} - -static inline void -dp_packet_set_flow_mark(struct dp_packet *p, uint32_t mark) -{ - p->flow_mark = mark; - p->ol_flags |= DP_PACKET_OL_FLOW_MARK_MASK; -} #endif /* DPDK_NETDEV */ static inline void @@ -1112,6 +888,58 @@ dp_packet_batch_reset_cutlen(struct dp_packet_batch *batch) } } +/* Returns the RSS hash of the packet 'p'. Note that the returned value is + * correct only if 'dp_packet_rss_valid(p)' returns 'true'. */ +static inline uint32_t +dp_packet_get_rss_hash(const struct dp_packet *p) +{ + return *dp_packet_rss_ptr(p); +} + +static inline void +dp_packet_set_rss_hash(struct dp_packet *p, uint32_t hash) +{ + *dp_packet_rss_ptr(p) = hash; + *dp_packet_ol_flags_ptr(p) |= DP_PACKET_OL_RSS_HASH; +} + +static inline bool +dp_packet_rss_valid(const struct dp_packet *p) +{ + return *dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RSS_HASH; +} + +static inline void +dp_packet_reset_offload(struct dp_packet *p) +{ + *dp_packet_ol_flags_ptr(p) &= ~DP_PACKET_OL_SUPPORTED_MASK; +} + +static inline bool +dp_packet_has_flow_mark(const struct dp_packet *p, uint32_t *mark) +{ + if (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_FLOW_MARK) { + *mark = *dp_packet_flow_mark_ptr(p); + return true; + } + + return false; +} + +static inline void +dp_packet_set_flow_mark(struct dp_packet *p, uint32_t mark) +{ + *dp_packet_flow_mark_ptr(p) = mark; + *dp_packet_ol_flags_ptr(p) |= DP_PACKET_OL_FLOW_MARK; +} + +/* Returns the L4 cksum offload bitmask. */ +static inline uint64_t +dp_packet_hwol_l4_mask(const struct dp_packet *b) +{ + return *dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK; +} + /* Return true if the packet 'b' requested L4 checksum offload. */ static inline bool dp_packet_hwol_tx_l4_checksum(const struct dp_packet *b) @@ -1119,6 +947,119 @@ dp_packet_hwol_tx_l4_checksum(const struct dp_packet *b) return !!dp_packet_hwol_l4_mask(b); } +/* Returns 'true' if packet 'b' is marked for TCP segmentation offloading. */ +static inline bool +dp_packet_hwol_is_tso(const struct dp_packet *b) +{ + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TCP_SEG); +} + +/* Returns 'true' if packet 'b' is marked for IPv4 checksum offloading. */ +static inline bool +dp_packet_hwol_is_ipv4(const struct dp_packet *b) +{ + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_IPV4); +} + +/* Returns 'true' if packet 'b' is marked for TCP checksum offloading. */ +static inline bool +dp_packet_hwol_l4_is_tcp(const struct dp_packet *b) +{ + return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == + DP_PACKET_OL_TX_TCP_CKSUM; +} + +/* Returns 'true' if packet 'b' is marked for UDP checksum offloading. */ +static inline bool +dp_packet_hwol_l4_is_udp(struct dp_packet *b) +{ + return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == + DP_PACKET_OL_TX_UDP_CKSUM; +} + +/* Returns 'true' if packet 'b' is marked for SCTP checksum offloading. */ +static inline bool +dp_packet_hwol_l4_is_sctp(struct dp_packet *b) +{ + return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == + DP_PACKET_OL_TX_SCTP_CKSUM; +} + +/* Mark packet 'b' for IPv4 checksum offloading. */ +static inline void +dp_packet_hwol_set_tx_ipv4(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_IPV4; +} + +/* Mark packet 'b' for IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_tx_ipv6(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_IPV6; +} + +/* Mark packet 'b' for TCP checksum offloading. It implies that either + * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_csum_tcp(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_CKSUM; +} + +/* Mark packet 'b' for UDP checksum offloading. It implies that either + * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_csum_udp(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_UDP_CKSUM; +} + +/* Mark packet 'b' for SCTP checksum offloading. It implies that either + * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_csum_sctp(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_SCTP_CKSUM; +} + +/* Mark packet 'b' for TCP segmentation offloading. It implies that + * either the packet 'b' is marked for IPv4 or IPv6 checksum offloading + * and also for TCP checksum offloading. */ +static inline void +dp_packet_hwol_set_tcp_seg(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_SEG; +} + +static inline bool +dp_packet_ip_checksum_valid(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_IP_CKSUM_MASK) == + DP_PACKET_OL_RX_IP_CKSUM_GOOD; +} + +static inline bool +dp_packet_ip_checksum_bad(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_IP_CKSUM_MASK) == + DP_PACKET_OL_RX_IP_CKSUM_BAD; +} + +static inline bool +dp_packet_l4_checksum_valid(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_L4_CKSUM_MASK) == + DP_PACKET_OL_RX_L4_CKSUM_GOOD; +} + +static inline bool +dp_packet_l4_checksum_bad(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_L4_CKSUM_MASK) == + DP_PACKET_OL_RX_L4_CKSUM_BAD; +} + #ifdef __cplusplus } #endif diff --git a/lib/userspace-tso.c b/lib/userspace-tso.c index 6a4a0149b7f..f843c2a763c 100644 --- a/lib/userspace-tso.c +++ b/lib/userspace-tso.c @@ -34,13 +34,8 @@ userspace_tso_init(const struct smap *ovs_other_config) static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; if (ovsthread_once_start(&once)) { -#ifdef DPDK_NETDEV VLOG_INFO("Userspace TCP Segmentation Offloading support enabled"); userspace_tso = true; -#else - VLOG_WARN("Userspace TCP Segmentation Offloading can not be enabled" - "since OVS is built without DPDK support."); -#endif ovsthread_once_done(&once); } } diff --git a/tests/.gitignore b/tests/.gitignore index 99fdf70d58c..45b4f67b2a4 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -24,6 +24,9 @@ /system-userspace-testsuite /system-userspace-testsuite.dir/ /system-userspace-testsuite.log +/system-tso-testsuite +/system-tso-testsuite.dir/ +/system-tso-testsuite.log /system-offloads-testsuite /system-offloads-testsuite.dir/ /system-offloads-testsuite.log diff --git a/tests/automake.mk b/tests/automake.mk index 81eb2a9b822..66859d5377c 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -4,6 +4,7 @@ EXTRA_DIST += \ $(SYSTEM_TESTSUITE_AT) \ $(SYSTEM_KMOD_TESTSUITE_AT) \ $(SYSTEM_USERSPACE_TESTSUITE_AT) \ + $(SYSTEM_TSO_TESTSUITE_AT) \ $(SYSTEM_AFXDP_TESTSUITE_AT) \ $(SYSTEM_OFFLOADS_TESTSUITE_AT) \ $(SYSTEM_DPDK_TESTSUITE_AT) \ @@ -11,6 +12,7 @@ EXTRA_DIST += \ $(TESTSUITE) \ $(SYSTEM_KMOD_TESTSUITE) \ $(SYSTEM_USERSPACE_TESTSUITE) \ + $(SYSTEM_TSO_TESTSUITE) \ $(SYSTEM_AFXDP_TESTSUITE) \ $(SYSTEM_OFFLOADS_TESTSUITE) \ $(SYSTEM_DPDK_TESTSUITE) \ @@ -154,6 +156,10 @@ SYSTEM_USERSPACE_TESTSUITE_AT = \ tests/system-userspace-macros.at \ tests/system-userspace-packet-type-aware.at +SYSTEM_TSO_TESTSUITE_AT = \ + tests/system-tso-testsuite.at \ + tests/system-tso-macros.at + SYSTEM_AFXDP_TESTSUITE_AT = \ tests/system-userspace-macros.at \ tests/system-afxdp-testsuite.at \ @@ -183,6 +189,7 @@ TESTSUITE = $(srcdir)/tests/testsuite TESTSUITE_PATCH = $(srcdir)/tests/testsuite.patch SYSTEM_KMOD_TESTSUITE = $(srcdir)/tests/system-kmod-testsuite SYSTEM_USERSPACE_TESTSUITE = $(srcdir)/tests/system-userspace-testsuite +SYSTEM_TSO_TESTSUITE = $(srcdir)/tests/system-tso-testsuite SYSTEM_AFXDP_TESTSUITE = $(srcdir)/tests/system-afxdp-testsuite SYSTEM_OFFLOADS_TESTSUITE = $(srcdir)/tests/system-offloads-testsuite SYSTEM_DPDK_TESTSUITE = $(srcdir)/tests/system-dpdk-testsuite @@ -296,6 +303,12 @@ check-offloads-valgrind: all $(valgrind_wrappers) $(check_DATA) @echo '----------------------------------------------------------------------' @echo 'Valgrind output can be found in tests/system-offloads-testsuite.dir/*/valgrind.*' @echo '----------------------------------------------------------------------' +check-tso-valgrind: all $(valgrind_wrappers) $(check_DATA) + $(SHELL) '$(SYSTEM_TSO_TESTSUITE)' -C tests VALGRIND='$(VALGRIND)' AUTOTEST_PATH='tests/valgrind:$(AUTOTEST_PATH)' -d $(TESTSUITEFLAGS) -j1 + @echo + @echo '----------------------------------------------------------------------' + @echo 'Valgrind output can be found in tests/system-tso-testsuite.dir/*/valgrind.*' + @echo '----------------------------------------------------------------------' check-helgrind: all $(valgrind_wrappers) $(check_DATA) -$(SHELL) '$(TESTSUITE)' -C tests CHECK_VALGRIND=true VALGRIND='$(HELGRIND)' AUTOTEST_PATH='tests/valgrind:$(AUTOTEST_PATH)' -d $(TESTSUITEFLAGS) @@ -326,6 +339,10 @@ check-system-userspace: all set $(SHELL) '$(SYSTEM_USERSPACE_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) +check-system-tso: all + set $(SHELL) '$(SYSTEM_TSO_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ + "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) + check-afxdp: all set $(SHELL) '$(SYSTEM_AFXDP_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)' $(TESTSUITEFLAGS) -j1; \ "$$@" || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) @@ -367,6 +384,10 @@ $(SYSTEM_USERSPACE_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_USERSP $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at $(AM_V_at)mv $@.tmp $@ +$(SYSTEM_TSO_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_TSO_TESTSUITE_AT) $(COMMON_MACROS_AT) + $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at + $(AM_V_at)mv $@.tmp $@ + $(SYSTEM_AFXDP_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_AFXDP_TESTSUITE_AT) $(COMMON_MACROS_AT) $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at $(AM_V_at)mv $@.tmp $@ diff --git a/tests/system-tso-macros.at b/tests/system-tso-macros.at new file mode 100644 index 00000000000..406334f3e08 --- /dev/null +++ b/tests/system-tso-macros.at @@ -0,0 +1,31 @@ +# _ADD_BR([name]) +# +# Expands into the proper ovs-vsctl commands to create a bridge with the +# appropriate type and properties +m4_define([_ADD_BR], [[add-br $1 -- set Bridge $1 datapath_type="netdev" protocols=OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15 fail-mode=secure ]]) + +# OVS_TRAFFIC_VSWITCHD_START([vsctl-args], [vsctl-output], [=override]) +# +# Creates a database and starts ovsdb-server, starts ovs-vswitchd +# connected to that database, calls ovs-vsctl to create a bridge named +# br0 with predictable settings, passing 'vsctl-args' as additional +# commands to ovs-vsctl. If 'vsctl-args' causes ovs-vsctl to provide +# output (e.g. because it includes "create" commands) then 'vsctl-output' +# specifies the expected output after filtering through uuidfilt. +m4_define([OVS_TRAFFIC_VSWITCHD_START], + [ + OVS_WAIT_WHILE([ip link show ovs-netdev]) + _OVS_VSWITCHD_START([--disable-system]) + dnl Add bridges, ports, etc. + OVS_WAIT_WHILE([ip link show br0]) + AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:userspace-tso-enable=true]) + AT_CHECK([ovs-vsctl -- _ADD_BR([br0]) -- $1 m4_if([$2], [], [], [| uuidfilt])], [0], [$2]) +]) + +# CONFIGURE_VETH_OFFLOADS([VETH]) +# +# Enable TCP segmentation offload and scatter-gather for veths. +m4_define([CONFIGURE_VETH_OFFLOADS], + [AT_CHECK([ethtool -K $1 sg on], [0], [ignore], [ignore])] + [AT_CHECK([ethtool -K $1 tso on], [0], [ignore], [ignore])] +) diff --git a/tests/system-tso-testsuite.at b/tests/system-tso-testsuite.at new file mode 100644 index 00000000000..99d748006a8 --- /dev/null +++ b/tests/system-tso-testsuite.at @@ -0,0 +1,26 @@ +AT_INIT + +AT_COPYRIGHT([Copyright (c) 2020 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.]) + +m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS]) + +m4_include([tests/ovs-macros.at]) +m4_include([tests/ovsdb-macros.at]) +m4_include([tests/ofproto-macros.at]) +m4_include([tests/system-common-macros.at]) +m4_include([tests/system-userspace-macros.at]) +m4_include([tests/system-tso-macros.at]) + +m4_include([tests/system-traffic.at])