mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
dp-packet: Rework TCP segmentation.
Rather than mark with a offload flags + mark with a segmentation size, simply rely on the netdev implementation which sets a segmentation size when appropriate. Signed-off-by: David Marchand <david.marchand@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
parent
e36793e11f
commit
cf7b86db1f
@ -63,8 +63,6 @@ dp_packet_gso_seg_new(const struct dp_packet *p, size_t hdr_len,
|
|||||||
& DP_PACKET_OL_SUPPORTED_MASK;
|
& DP_PACKET_OL_SUPPORTED_MASK;
|
||||||
seg->offloads = p->offloads;
|
seg->offloads = p->offloads;
|
||||||
|
|
||||||
dp_packet_hwol_reset_tcp_seg(seg);
|
|
||||||
|
|
||||||
return seg;
|
return seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,16 +55,7 @@ enum OVS_PACKED_ENUM dp_packet_source {
|
|||||||
#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = GENERIC_DEF
|
#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = GENERIC_DEF
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Bit masks for the 'ol_flags' member of the 'dp_packet' structure. */
|
#define DP_PACKET_OL_SUPPORTED_MASK 0
|
||||||
enum {
|
|
||||||
/* Value 0 is not used. */
|
|
||||||
/* TCP Segmentation Offload. */
|
|
||||||
DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_SEG, RTE_MBUF_F_TX_TCP_SEG, 0x40),
|
|
||||||
|
|
||||||
/* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DP_PACKET_OL_SUPPORTED_MASK DP_PACKET_OL_TX_TCP_SEG
|
|
||||||
|
|
||||||
/* Bit masks for the 'offloads' member of the 'dp_packet' structure. */
|
/* Bit masks for the 'offloads' member of the 'dp_packet' structure. */
|
||||||
enum OVS_PACKED_ENUM dp_packet_offload_mask {
|
enum OVS_PACKED_ENUM dp_packet_offload_mask {
|
||||||
@ -1122,29 +1113,6 @@ dp_packet_tunnel(const struct dp_packet *b)
|
|||||||
return !!(b->offloads & DP_PACKET_OL_TUNNEL_MASK);
|
return !!(b->offloads & DP_PACKET_OL_TUNNEL_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resets TCP Segmentation in packet 'p'. */
|
|
||||||
static inline void
|
|
||||||
dp_packet_hwol_reset_tcp_seg(struct dp_packet *p)
|
|
||||||
{
|
|
||||||
*dp_packet_ol_flags_ptr(p) &= ~DP_PACKET_OL_TX_TCP_SEG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Marks packet 'p' with good IPv4 checksum. */
|
/* Marks packet 'p' with good IPv4 checksum. */
|
||||||
static inline void
|
static inline void
|
||||||
dp_packet_ip_checksum_set_good(struct dp_packet *p)
|
dp_packet_ip_checksum_set_good(struct dp_packet *p)
|
||||||
|
@ -2661,13 +2661,11 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
|
|||||||
void *l3;
|
void *l3;
|
||||||
void *l4;
|
void *l4;
|
||||||
|
|
||||||
const uint64_t all_inner_requests = RTE_MBUF_F_TX_TCP_SEG;
|
|
||||||
|
|
||||||
if (!dp_packet_ip_checksum_partial(pkt)
|
if (!dp_packet_ip_checksum_partial(pkt)
|
||||||
&& !dp_packet_inner_ip_checksum_partial(pkt)
|
&& !dp_packet_inner_ip_checksum_partial(pkt)
|
||||||
&& !dp_packet_l4_checksum_partial(pkt)
|
&& !dp_packet_l4_checksum_partial(pkt)
|
||||||
&& !dp_packet_inner_l4_checksum_partial(pkt)
|
&& !dp_packet_inner_l4_checksum_partial(pkt)
|
||||||
&& !(mbuf->ol_flags & all_inner_requests)) {
|
&& !mbuf->tso_segsz) {
|
||||||
|
|
||||||
uint64_t unexpected = mbuf->ol_flags & RTE_MBUF_F_TX_OFFLOAD_MASK;
|
uint64_t unexpected = mbuf->ol_flags & RTE_MBUF_F_TX_OFFLOAD_MASK;
|
||||||
if (OVS_UNLIKELY(unexpected)) {
|
if (OVS_UNLIKELY(unexpected)) {
|
||||||
@ -2683,7 +2681,7 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
|
|||||||
if (dp_packet_tunnel(pkt)
|
if (dp_packet_tunnel(pkt)
|
||||||
&& (dp_packet_inner_ip_checksum_partial(pkt)
|
&& (dp_packet_inner_ip_checksum_partial(pkt)
|
||||||
|| dp_packet_inner_l4_checksum_partial(pkt)
|
|| dp_packet_inner_l4_checksum_partial(pkt)
|
||||||
|| (mbuf->ol_flags & all_inner_requests))) {
|
|| mbuf->tso_segsz)) {
|
||||||
if (dp_packet_ip_checksum_partial(pkt)
|
if (dp_packet_ip_checksum_partial(pkt)
|
||||||
|| dp_packet_l4_checksum_partial(pkt)) {
|
|| dp_packet_l4_checksum_partial(pkt)) {
|
||||||
mbuf->outer_l2_len = (char *) dp_packet_l3(pkt) -
|
mbuf->outer_l2_len = (char *) dp_packet_l3(pkt) -
|
||||||
@ -2775,7 +2773,7 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
|
|||||||
mbuf->l2_len = (char *) l3 - (char *) l2;
|
mbuf->l2_len = (char *) l3 - (char *) l2;
|
||||||
mbuf->l3_len = (char *) l4 - (char *) l3;
|
mbuf->l3_len = (char *) l4 - (char *) l3;
|
||||||
|
|
||||||
if (mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
|
if (mbuf->tso_segsz) {
|
||||||
struct tcp_header *th = l4;
|
struct tcp_header *th = l4;
|
||||||
uint16_t link_tso_segsz;
|
uint16_t link_tso_segsz;
|
||||||
int hdr_len;
|
int hdr_len;
|
||||||
@ -2800,6 +2798,7 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
|
|||||||
dev->max_packet_len);
|
dev->max_packet_len);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
mbuf->ol_flags |= RTE_MBUF_F_TX_TCP_SEG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If L4 checksum is requested, IPv4 should be requested as well. */
|
/* If L4 checksum is requested, IPv4 should be requested as well. */
|
||||||
@ -3113,7 +3112,7 @@ netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, struct rte_mbuf **pkts,
|
|||||||
for (i = 0; i < pkt_cnt; i++) {
|
for (i = 0; i < pkt_cnt; i++) {
|
||||||
pkt = pkts[i];
|
pkt = pkts[i];
|
||||||
if (OVS_UNLIKELY((pkt->pkt_len > dev->max_packet_len)
|
if (OVS_UNLIKELY((pkt->pkt_len > dev->max_packet_len)
|
||||||
&& !(pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG))) {
|
&& !pkt->tso_segsz)) {
|
||||||
VLOG_WARN_RL(&rl, "%s: Too big size %" PRIu32 " "
|
VLOG_WARN_RL(&rl, "%s: Too big size %" PRIu32 " "
|
||||||
"max_packet_len %d", dev->up.name, pkt->pkt_len,
|
"max_packet_len %d", dev->up.name, pkt->pkt_len,
|
||||||
dev->max_packet_len);
|
dev->max_packet_len);
|
||||||
|
@ -1223,7 +1223,6 @@ netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch,
|
|||||||
|
|
||||||
if (userspace_tso_enabled() && netdev->ol_tso_segsz) {
|
if (userspace_tso_enabled() && netdev->ol_tso_segsz) {
|
||||||
dp_packet_set_tso_segsz(packet, netdev->ol_tso_segsz);
|
dp_packet_set_tso_segsz(packet, netdev->ol_tso_segsz);
|
||||||
dp_packet_hwol_set_tcp_seg(packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VLOG_IS_DBG_ENABLED()) {
|
if (VLOG_IS_DBG_ENABLED()) {
|
||||||
@ -1312,7 +1311,7 @@ netdev_dummy_send(struct netdev *netdev, int qid,
|
|||||||
flags &= ~NETDEV_TX_OFFLOAD_UDP_CKSUM;
|
flags &= ~NETDEV_TX_OFFLOAD_UDP_CKSUM;
|
||||||
}
|
}
|
||||||
is_tso = userspace_tso_enabled() && dev->ol_tso_segsz &&
|
is_tso = userspace_tso_enabled() && dev->ol_tso_segsz &&
|
||||||
dp_packet_hwol_is_tso(packet);
|
dp_packet_get_tso_segsz(packet);
|
||||||
ovs_mutex_unlock(&dev->mutex);
|
ovs_mutex_unlock(&dev->mutex);
|
||||||
|
|
||||||
if (!dp_packet_is_eth(packet)) {
|
if (!dp_packet_is_eth(packet)) {
|
||||||
@ -1350,14 +1349,12 @@ netdev_dummy_send(struct netdev *netdev, int qid,
|
|||||||
ip_csum_bad = !!(packet->offloads & DP_PACKET_OL_IP_CKSUM_BAD);
|
ip_csum_bad = !!(packet->offloads & DP_PACKET_OL_IP_CKSUM_BAD);
|
||||||
l4_csum_good = !!(packet->offloads & DP_PACKET_OL_L4_CKSUM_GOOD);
|
l4_csum_good = !!(packet->offloads & DP_PACKET_OL_L4_CKSUM_GOOD);
|
||||||
l4_csum_bad = !!(packet->offloads & DP_PACKET_OL_L4_CKSUM_BAD);
|
l4_csum_bad = !!(packet->offloads & DP_PACKET_OL_L4_CKSUM_BAD);
|
||||||
VLOG_DBG("Tx: packet with csum IP %s, L4 %s, segsz %"PRIu16
|
VLOG_DBG("Tx: packet with csum IP %s, L4 %s, segsz %"PRIu16,
|
||||||
", Tx flags %s",
|
|
||||||
ip_csum_good ? (ip_csum_bad ? "partial" : "good")
|
ip_csum_good ? (ip_csum_bad ? "partial" : "good")
|
||||||
: (ip_csum_bad ? "bad" : "unknown"),
|
: (ip_csum_bad ? "bad" : "unknown"),
|
||||||
l4_csum_good ? (l4_csum_bad ? "partial" : "good")
|
l4_csum_good ? (l4_csum_bad ? "partial" : "good")
|
||||||
: (l4_csum_bad ? "bad" : "unknown"),
|
: (l4_csum_bad ? "bad" : "unknown"),
|
||||||
dp_packet_get_tso_segsz(packet),
|
dp_packet_get_tso_segsz(packet));
|
||||||
dp_packet_hwol_is_tso(packet) ? "tso" : "none");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dp_packet_ip_checksum_partial(packet)
|
if (dp_packet_ip_checksum_partial(packet)
|
||||||
|
@ -7104,7 +7104,6 @@ netdev_linux_parse_vnet_hdr(struct dp_packet *b)
|
|||||||
case VIRTIO_NET_HDR_GSO_TCPV4:
|
case VIRTIO_NET_HDR_GSO_TCPV4:
|
||||||
case VIRTIO_NET_HDR_GSO_TCPV6:
|
case VIRTIO_NET_HDR_GSO_TCPV6:
|
||||||
dp_packet_set_tso_segsz(b, (OVS_FORCE uint16_t) vnet->gso_size);
|
dp_packet_set_tso_segsz(b, (OVS_FORCE uint16_t) vnet->gso_size);
|
||||||
dp_packet_hwol_set_tcp_seg(b);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIRTIO_NET_HDR_GSO_UDP:
|
case VIRTIO_NET_HDR_GSO_UDP:
|
||||||
@ -7134,7 +7133,7 @@ netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
|
|||||||
struct virtio_net_hdr v;
|
struct virtio_net_hdr v;
|
||||||
struct virtio_net_hdr *vnet = &v;
|
struct virtio_net_hdr *vnet = &v;
|
||||||
|
|
||||||
if (dp_packet_hwol_is_tso(b)) {
|
if (dp_packet_get_tso_segsz(b)) {
|
||||||
uint16_t tso_segsz = dp_packet_get_tso_segsz(b);
|
uint16_t tso_segsz = dp_packet_get_tso_segsz(b);
|
||||||
const struct tcp_header *tcp;
|
const struct tcp_header *tcp;
|
||||||
const struct ip_header *ip;
|
const struct ip_header *ip;
|
||||||
|
@ -548,7 +548,7 @@ netdev_gre_push_header(const struct netdev *netdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (greh->flags & htons(GRE_SEQ)) {
|
if (greh->flags & htons(GRE_SEQ)) {
|
||||||
if (!dp_packet_hwol_is_tso(packet)) {
|
if (!dp_packet_get_tso_segsz(packet)) {
|
||||||
/* Last 4 bytes are GRE seqno. */
|
/* Last 4 bytes are GRE seqno. */
|
||||||
int seq_ofs = gre_header_len(greh->flags) - 4;
|
int seq_ofs = gre_header_len(greh->flags) - 4;
|
||||||
ovs_16aligned_be32 *seq_opt =
|
ovs_16aligned_be32 *seq_opt =
|
||||||
|
14
lib/netdev.c
14
lib/netdev.c
@ -816,7 +816,7 @@ netdev_send_tso(struct netdev *netdev, int qid,
|
|||||||
* the segmentation. */
|
* the segmentation. */
|
||||||
n_packets = 0;
|
n_packets = 0;
|
||||||
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
||||||
if (dp_packet_hwol_is_tso(packet)) {
|
if (dp_packet_get_tso_segsz(packet)) {
|
||||||
n_packets += dp_packet_gso_nr_segs(packet);
|
n_packets += dp_packet_gso_nr_segs(packet);
|
||||||
} else {
|
} else {
|
||||||
n_packets++;
|
n_packets++;
|
||||||
@ -842,7 +842,7 @@ netdev_send_tso(struct netdev *netdev, int qid,
|
|||||||
size_t k;
|
size_t k;
|
||||||
curr_batch = batches;
|
curr_batch = batches;
|
||||||
DP_PACKET_BATCH_REFILL_FOR_EACH (k, size, packet, batch) {
|
DP_PACKET_BATCH_REFILL_FOR_EACH (k, size, packet, batch) {
|
||||||
if (dp_packet_hwol_is_tso(packet)) {
|
if (dp_packet_get_tso_segsz(packet)) {
|
||||||
if (dp_packet_gso(packet, &curr_batch)) {
|
if (dp_packet_gso(packet, &curr_batch)) {
|
||||||
COVERAGE_INC(netdev_soft_seg_good);
|
COVERAGE_INC(netdev_soft_seg_good);
|
||||||
} else {
|
} else {
|
||||||
@ -911,7 +911,7 @@ netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
|
|||||||
if (userspace_tso_enabled()) {
|
if (userspace_tso_enabled()) {
|
||||||
if (!(netdev_flags & NETDEV_TX_OFFLOAD_TCP_TSO)) {
|
if (!(netdev_flags & NETDEV_TX_OFFLOAD_TCP_TSO)) {
|
||||||
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
||||||
if (dp_packet_hwol_is_tso(packet)) {
|
if (dp_packet_get_tso_segsz(packet)) {
|
||||||
return netdev_send_tso(netdev, qid, batch, concurrent_txq);
|
return netdev_send_tso(netdev, qid, batch, concurrent_txq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -919,14 +919,14 @@ netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
|
|||||||
NETDEV_TX_GRE_TNL_TSO |
|
NETDEV_TX_GRE_TNL_TSO |
|
||||||
NETDEV_TX_GENEVE_TNL_TSO))) {
|
NETDEV_TX_GENEVE_TNL_TSO))) {
|
||||||
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
||||||
if (dp_packet_hwol_is_tso(packet)
|
if (dp_packet_get_tso_segsz(packet)
|
||||||
&& dp_packet_tunnel(packet)) {
|
&& dp_packet_tunnel(packet)) {
|
||||||
return netdev_send_tso(netdev, qid, batch, concurrent_txq);
|
return netdev_send_tso(netdev, qid, batch, concurrent_txq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!(netdev_flags & NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM)) {
|
} else if (!(netdev_flags & NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM)) {
|
||||||
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
|
||||||
if (dp_packet_hwol_is_tso(packet)
|
if (dp_packet_get_tso_segsz(packet)
|
||||||
&& (dp_packet_tunnel_vxlan(packet)
|
&& (dp_packet_tunnel_vxlan(packet)
|
||||||
|| dp_packet_tunnel_geneve(packet))
|
|| dp_packet_tunnel_geneve(packet))
|
||||||
&& dp_packet_l4_checksum_partial(packet)) {
|
&& dp_packet_l4_checksum_partial(packet)) {
|
||||||
@ -1013,7 +1013,7 @@ netdev_push_header(const struct netdev *netdev,
|
|||||||
data->tnl_type != OVS_VPORT_TYPE_VXLAN &&
|
data->tnl_type != OVS_VPORT_TYPE_VXLAN &&
|
||||||
data->tnl_type != OVS_VPORT_TYPE_GRE &&
|
data->tnl_type != OVS_VPORT_TYPE_GRE &&
|
||||||
data->tnl_type != OVS_VPORT_TYPE_IP6GRE &&
|
data->tnl_type != OVS_VPORT_TYPE_IP6GRE &&
|
||||||
dp_packet_hwol_is_tso(packet))) {
|
dp_packet_get_tso_segsz(packet))) {
|
||||||
COVERAGE_INC(netdev_push_header_drops);
|
COVERAGE_INC(netdev_push_header_drops);
|
||||||
dp_packet_delete(packet);
|
dp_packet_delete(packet);
|
||||||
VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
|
VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
|
||||||
@ -1026,7 +1026,7 @@ netdev_push_header(const struct netdev *netdev,
|
|||||||
data->tnl_type != OVS_VPORT_TYPE_IP6GRE) {
|
data->tnl_type != OVS_VPORT_TYPE_IP6GRE) {
|
||||||
dp_packet_ol_send_prepare(packet, 0);
|
dp_packet_ol_send_prepare(packet, 0);
|
||||||
} else if (dp_packet_tunnel(packet)) {
|
} else if (dp_packet_tunnel(packet)) {
|
||||||
if (dp_packet_hwol_is_tso(packet)) {
|
if (dp_packet_get_tso_segsz(packet)) {
|
||||||
COVERAGE_INC(netdev_push_header_drops);
|
COVERAGE_INC(netdev_push_header_drops);
|
||||||
dp_packet_delete(packet);
|
dp_packet_delete(packet);
|
||||||
VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
|
VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user