Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2017 Intel Corporation 3 : : */ 4 : : 5 : : #include <stdbool.h> 6 : : #include <errno.h> 7 : : 8 : : #include <rte_memcpy.h> 9 : : 10 : : #include "gso_common.h" 11 : : 12 : : static inline void 13 : 0 : hdr_segment_init(struct rte_mbuf *hdr_segment, struct rte_mbuf *pkt, 14 : : uint16_t pkt_hdr_offset) 15 : : { 16 : : /* Copy MBUF metadata */ 17 : 0 : hdr_segment->nb_segs = 1; 18 : 0 : hdr_segment->port = pkt->port; 19 : 0 : hdr_segment->ol_flags = pkt->ol_flags; 20 : 0 : hdr_segment->packet_type = pkt->packet_type; 21 : 0 : hdr_segment->pkt_len = pkt_hdr_offset; 22 : 0 : hdr_segment->data_len = pkt_hdr_offset; 23 : 0 : hdr_segment->tx_offload = pkt->tx_offload; 24 : : 25 : : /* Copy the packet header */ 26 : 0 : rte_memcpy(rte_pktmbuf_mtod(hdr_segment, char *), 27 [ # # ]: 0 : rte_pktmbuf_mtod(pkt, char *), 28 : : pkt_hdr_offset); 29 : 0 : } 30 : : 31 : : static inline void 32 : : free_gso_segment(struct rte_mbuf **pkts, uint16_t nb_pkts) 33 : : { 34 : : uint16_t i; 35 : : 36 [ # # # # : 0 : for (i = 0; i < nb_pkts; i++) # # ] 37 : 0 : rte_pktmbuf_free(pkts[i]); 38 : : } 39 : : 40 : : int 41 : 0 : gso_do_segment(struct rte_mbuf *pkt, 42 : : uint16_t pkt_hdr_offset, 43 : : uint16_t pyld_unit_size, 44 : : struct rte_mempool *direct_pool, 45 : : struct rte_mempool *indirect_pool, 46 : : struct rte_mbuf **pkts_out, 47 : : uint16_t nb_pkts_out) 48 : : { 49 : : struct rte_mbuf *pkt_in; 50 : : struct rte_mbuf *hdr_segment, *pyld_segment, *prev_segment; 51 : : uint16_t pkt_in_data_pos, segment_bytes_remaining; 52 : : uint16_t pyld_len, nb_segs; 53 : : bool more_in_pkt, more_out_segs; 54 : : 55 : : pkt_in = pkt; 56 : : nb_segs = 0; 57 : : more_in_pkt = 1; 58 : : pkt_in_data_pos = pkt_hdr_offset; 59 : : 60 [ # # ]: 0 : while (more_in_pkt) { 61 [ # # ]: 0 : if (unlikely(nb_segs >= nb_pkts_out)) { 62 : : free_gso_segment(pkts_out, nb_segs); 63 : : return -EINVAL; 64 : : } 65 : : 66 : : /* Allocate a direct MBUF */ 67 : 0 : hdr_segment = rte_pktmbuf_alloc(direct_pool); 68 [ # # ]: 0 : if (unlikely(hdr_segment == NULL)) { 69 : : free_gso_segment(pkts_out, nb_segs); 70 : : return -ENOMEM; 71 : : } 72 : : /* Fill the packet header */ 73 : 0 : hdr_segment_init(hdr_segment, pkt, pkt_hdr_offset); 74 : : 75 : : prev_segment = hdr_segment; 76 : : segment_bytes_remaining = pyld_unit_size; 77 : : more_out_segs = 1; 78 : : 79 [ # # ]: 0 : while (more_out_segs && more_in_pkt) { 80 : : /* Allocate an indirect MBUF */ 81 : 0 : pyld_segment = rte_pktmbuf_alloc(indirect_pool); 82 [ # # ]: 0 : if (unlikely(pyld_segment == NULL)) { 83 : 0 : rte_pktmbuf_free(hdr_segment); 84 : : free_gso_segment(pkts_out, nb_segs); 85 : : return -ENOMEM; 86 : : } 87 : : /* Attach to current MBUF segment of pkt */ 88 : 0 : rte_pktmbuf_attach(pyld_segment, pkt_in); 89 : : 90 : 0 : prev_segment->next = pyld_segment; 91 : : prev_segment = pyld_segment; 92 : : 93 : : pyld_len = segment_bytes_remaining; 94 [ # # ]: 0 : if (pyld_len + pkt_in_data_pos > pkt_in->data_len) 95 : 0 : pyld_len = pkt_in->data_len - pkt_in_data_pos; 96 : : 97 : 0 : pyld_segment->data_off = pkt_in_data_pos + 98 : 0 : pkt_in->data_off; 99 : 0 : pyld_segment->data_len = pyld_len; 100 : : 101 : : /* Update header segment */ 102 : 0 : hdr_segment->pkt_len += pyld_len; 103 : 0 : hdr_segment->nb_segs++; 104 : : 105 : 0 : pkt_in_data_pos += pyld_len; 106 : 0 : segment_bytes_remaining -= pyld_len; 107 : : 108 : : /* Finish processing a MBUF segment of pkt */ 109 [ # # ]: 0 : if (pkt_in_data_pos == pkt_in->data_len) { 110 : 0 : pkt_in = pkt_in->next; 111 : : pkt_in_data_pos = 0; 112 [ # # ]: 0 : if (pkt_in == NULL) 113 : : more_in_pkt = 0; 114 : : } 115 : : 116 : : /* Finish generating a GSO segment */ 117 [ # # ]: 0 : if (segment_bytes_remaining == 0) 118 : : more_out_segs = 0; 119 : : } 120 : 0 : pkts_out[nb_segs++] = hdr_segment; 121 : : } 122 : 0 : return nb_segs; 123 : : }