1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Intel Corporation 3 */ 4 5 #include <errno.h> 6 7 #include <rte_log.h> 8 #include <rte_ethdev.h> 9 10 #include "rte_gso.h" 11 #include "gso_common.h" 12 #include "gso_tcp4.h" 13 #include "gso_tunnel_tcp4.h" 14 #include "gso_tunnel_udp4.h" 15 #include "gso_udp4.h" 16 17 #define ILLEGAL_UDP_GSO_CTX(ctx) \ 18 ((((ctx)->gso_types & RTE_ETH_TX_OFFLOAD_UDP_TSO) == 0) || \ 19 (ctx)->gso_size < RTE_GSO_UDP_SEG_SIZE_MIN) 20 21 #define ILLEGAL_TCP_GSO_CTX(ctx) \ 22 ((((ctx)->gso_types & (RTE_ETH_TX_OFFLOAD_TCP_TSO | \ 23 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO | \ 24 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO)) == 0) || \ 25 (ctx)->gso_size < RTE_GSO_SEG_SIZE_MIN) 26 27 int 28 rte_gso_segment(struct rte_mbuf *pkt, 29 const struct rte_gso_ctx *gso_ctx, 30 struct rte_mbuf **pkts_out, 31 uint16_t nb_pkts_out) 32 { 33 struct rte_mempool *direct_pool, *indirect_pool; 34 uint64_t ol_flags; 35 uint16_t gso_size; 36 uint8_t ipid_delta; 37 int ret = 1; 38 39 if (pkt == NULL || pkts_out == NULL || gso_ctx == NULL || 40 nb_pkts_out < 1 || 41 (ILLEGAL_UDP_GSO_CTX(gso_ctx) && 42 ILLEGAL_TCP_GSO_CTX(gso_ctx))) 43 return -EINVAL; 44 45 if (gso_ctx->gso_size >= pkt->pkt_len) { 46 pkt->ol_flags &= (~(RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG)); 47 return 0; 48 } 49 50 direct_pool = gso_ctx->direct_pool; 51 indirect_pool = gso_ctx->indirect_pool; 52 gso_size = gso_ctx->gso_size; 53 ipid_delta = (gso_ctx->flag != RTE_GSO_FLAG_IPID_FIXED); 54 ol_flags = pkt->ol_flags; 55 56 if ((IS_IPV4_VXLAN_TCP4(pkt->ol_flags) && 57 (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO)) || 58 ((IS_IPV4_GRE_TCP4(pkt->ol_flags) && 59 (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO)))) { 60 pkt->ol_flags &= (~RTE_MBUF_F_TX_TCP_SEG); 61 ret = gso_tunnel_tcp4_segment(pkt, gso_size, ipid_delta, 62 direct_pool, indirect_pool, 63 pkts_out, nb_pkts_out); 64 } else if (IS_IPV4_VXLAN_UDP4(pkt->ol_flags) && 65 (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) && 66 (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_UDP_TSO)) { 67 pkt->ol_flags &= (~RTE_MBUF_F_TX_UDP_SEG); 68 ret = gso_tunnel_udp4_segment(pkt, gso_size, 69 direct_pool, indirect_pool, 70 pkts_out, nb_pkts_out); 71 } else if (IS_IPV4_TCP(pkt->ol_flags) && 72 (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_TCP_TSO)) { 73 pkt->ol_flags &= (~RTE_MBUF_F_TX_TCP_SEG); 74 ret = gso_tcp4_segment(pkt, gso_size, ipid_delta, 75 direct_pool, indirect_pool, 76 pkts_out, nb_pkts_out); 77 } else if (IS_IPV4_UDP(pkt->ol_flags) && 78 (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_UDP_TSO)) { 79 pkt->ol_flags &= (~RTE_MBUF_F_TX_UDP_SEG); 80 ret = gso_udp4_segment(pkt, gso_size, direct_pool, 81 indirect_pool, pkts_out, nb_pkts_out); 82 } else { 83 ret = -ENOTSUP; /* only UDP or TCP allowed */ 84 } 85 86 if (ret < 0) { 87 /* Revert the ol_flags in the event of failure. */ 88 pkt->ol_flags = ol_flags; 89 } 90 91 return ret; 92 } 93