| 8 | #define IPV4_HDR_MF_BIT (1U << 13) |
| 9 | |
| 10 | static inline void |
| 11 | update_ipv4_udp_headers(struct rte_mbuf *pkt, struct rte_mbuf **segs, |
| 12 | uint16_t nb_segs) |
| 13 | { |
| 14 | struct rte_ipv4_hdr *ipv4_hdr; |
| 15 | uint16_t frag_offset = 0, is_mf; |
| 16 | uint16_t l2_hdrlen = pkt->l2_len, l3_hdrlen = pkt->l3_len; |
| 17 | uint16_t tail_idx = nb_segs - 1, length, i; |
| 18 | |
| 19 | /* |
| 20 | * Update IP header fields for output segments. Specifically, |
| 21 | * keep the same IP id, update fragment offset and total |
| 22 | * length. |
| 23 | */ |
| 24 | for (i = 0; i < nb_segs; i++) { |
| 25 | ipv4_hdr = rte_pktmbuf_mtod_offset(segs[i], |
| 26 | struct rte_ipv4_hdr *, l2_hdrlen); |
| 27 | length = segs[i]->pkt_len - l2_hdrlen; |
| 28 | ipv4_hdr->total_length = rte_cpu_to_be_16(length); |
| 29 | |
| 30 | is_mf = i < tail_idx ? IPV4_HDR_MF_BIT : 0; |
| 31 | ipv4_hdr->fragment_offset = |
| 32 | rte_cpu_to_be_16(frag_offset | is_mf); |
| 33 | frag_offset += ((length - l3_hdrlen) >> 3); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | int |
| 38 | gso_udp4_segment(struct rte_mbuf *pkt, |