update original ip header fields for transport case */
| 39 | |
| 40 | /* update original ip header fields for transport case */ |
| 41 | static inline int |
| 42 | update_trs_l3hdr(const struct rte_ipsec_sa *sa, void *p, uint32_t plen, |
| 43 | uint32_t l2len, uint32_t l3len, uint8_t proto) |
| 44 | { |
| 45 | int32_t rc; |
| 46 | |
| 47 | /* IPv4 */ |
| 48 | if ((sa->type & RTE_IPSEC_SATP_IPV_MASK) == RTE_IPSEC_SATP_IPV4) { |
| 49 | struct rte_ipv4_hdr *v4h; |
| 50 | |
| 51 | v4h = p; |
| 52 | rc = v4h->next_proto_id; |
| 53 | v4h->next_proto_id = proto; |
| 54 | v4h->total_length = rte_cpu_to_be_16(plen - l2len); |
| 55 | /* IPv6 */ |
| 56 | } else { |
| 57 | struct rte_ipv6_hdr *v6h; |
| 58 | uint8_t *p_nh; |
| 59 | |
| 60 | v6h = p; |
| 61 | |
| 62 | /* basic IPv6 header with no extensions */ |
| 63 | if (l3len == sizeof(struct rte_ipv6_hdr)) |
| 64 | p_nh = &v6h->proto; |
| 65 | |
| 66 | /* IPv6 with extensions */ |
| 67 | else { |
| 68 | size_t ext_len; |
| 69 | int nh; |
| 70 | uint8_t *pd, *plimit; |
| 71 | |
| 72 | /* locate last extension within l3len bytes */ |
| 73 | pd = (uint8_t *)p; |
| 74 | plimit = pd + l3len; |
| 75 | ext_len = sizeof(struct rte_ipv6_hdr); |
| 76 | nh = v6h->proto; |
| 77 | while (pd + ext_len < plimit) { |
| 78 | pd += ext_len; |
| 79 | nh = rte_ipv6_get_next_ext(pd, nh, &ext_len); |
| 80 | if (unlikely(nh < 0)) |
| 81 | return -EINVAL; |
| 82 | } |
| 83 | |
| 84 | /* invalid l3len - extension exceeds header length */ |
| 85 | if (unlikely(pd + ext_len != plimit)) |
| 86 | return -EINVAL; |
| 87 | |
| 88 | /* save last extension offset */ |
| 89 | p_nh = pd; |
| 90 | } |
| 91 | |
| 92 | /* update header type; return original value */ |
| 93 | rc = *p_nh; |
| 94 | *p_nh = proto; |
| 95 | |
| 96 | /* fix packet length */ |
| 97 | v6h->payload_len = rte_cpu_to_be_16(plen - l2len - |
| 98 | sizeof(*v6h)); |
no test coverage detected